[kernel] r10992 - in dists/trunk/linux-2.6/debian/patches: bugfix/all series

Maximilian Attems maks at alioth.debian.org
Fri Mar 28 17:54:15 UTC 2008


Author: maks
Date: Fri Mar 28 17:54:14 2008
New Revision: 10992

Log:
update to 2.6.25-rc7-git3

nuke smctr patch.
sparc64, x86, acpi, net fixes.


Added:
   dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-rc7-git3
Removed:
   dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-rc7-git2
Modified:
   dists/trunk/linux-2.6/debian/patches/series/1~experimental.1

Added: dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-rc7-git3
==============================================================================
--- (empty file)
+++ dists/trunk/linux-2.6/debian/patches/bugfix/all/patch-2.6.25-rc7-git3	Fri Mar 28 17:54:14 2008
@@ -0,0 +1,5650 @@
+diff --git a/Documentation/i386/IO-APIC.txt b/Documentation/i386/IO-APIC.txt
+index f951666..30b4c71 100644
+--- a/Documentation/i386/IO-APIC.txt
++++ b/Documentation/i386/IO-APIC.txt
+@@ -70,7 +70,7 @@ Every PCI card emits a PCI IRQ, which can be INTA, INTB, INTC or INTD:
+ 
+ These INTA-D PCI IRQs are always 'local to the card', their real meaning
+ depends on which slot they are in. If you look at the daisy chaining diagram,
+-a card in slot4, issuing INTA IRQ, it will end up as a signal on PIRQ2 of
++a card in slot4, issuing INTA IRQ, it will end up as a signal on PIRQ4 of
+ the PCI chipset. Most cards issue INTA, this creates optimal distribution
+ between the PIRQ lines. (distributing IRQ sources properly is not a
+ necessity, PCI IRQs can be shared at will, but it's a good for performance
+diff --git a/Documentation/nmi_watchdog.txt b/Documentation/nmi_watchdog.txt
+index c025a45..757c729 100644
+--- a/Documentation/nmi_watchdog.txt
++++ b/Documentation/nmi_watchdog.txt
+@@ -23,8 +23,7 @@ kernel debugging options, such as Kernel Stack Meter or Kernel Tracer,
+ may implicitly disable the NMI watchdog.]
+ 
+ For x86-64, the needed APIC is always compiled in, and the NMI watchdog is
+-always enabled with I/O-APIC mode (nmi_watchdog=1). Currently, local APIC
+-mode (nmi_watchdog=2) does not work on x86-64.
++always enabled with I/O-APIC mode (nmi_watchdog=1).
+ 
+ Using local APIC (nmi_watchdog=2) needs the first performance register, so
+ you can't use it for other purposes (such as high precision performance
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 73883b8..f1ed75c 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -2110,7 +2110,7 @@ M:	reinette.chatre at intel.com
+ L:	linux-wireless at vger.kernel.org
+ L:	ipw3945-devel at lists.sourceforge.net
+ W:	http://intellinuxwireless.org
+-T:	git git://intellinuxwireless.org/repos/iwlwifi
++T:	git git://git.kernel.org/pub/scm/linux/kernel/git/rchatre/iwlwifi-2.6.git
+ S:	Supported
+ 
+ IOC3 ETHERNET DRIVER
+@@ -2322,6 +2322,8 @@ P:	Anil S Keshavamurthy
+ M:	anil.s.keshavamurthy at intel.com
+ P:	David S. Miller
+ M:	davem at davemloft.net
++P:	Masami Hiramatsu
++M:	mhiramat at redhat.com
+ L:	linux-kernel at vger.kernel.org
+ S:	Maintained
+ 
+diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c
+index e66a07a..2687b73 100644
+--- a/arch/avr32/kernel/setup.c
++++ b/arch/avr32/kernel/setup.c
+@@ -163,6 +163,7 @@ add_reserved_region(resource_size_t start, resource_size_t end,
+ 	new->start = start;
+ 	new->end = end;
+ 	new->name = name;
++	new->sibling = next;
+ 	new->flags = IORESOURCE_MEM;
+ 
+ 	*pprev = new;
+diff --git a/arch/avr32/kernel/traps.c b/arch/avr32/kernel/traps.c
+index cf6f686..b835c4c 100644
+--- a/arch/avr32/kernel/traps.c
++++ b/arch/avr32/kernel/traps.c
+@@ -178,6 +178,7 @@ static int do_cop_absent(u32 insn)
+ 	return 0;
+ }
+ 
++#ifdef CONFIG_BUG
+ int is_valid_bugaddr(unsigned long pc)
+ {
+ 	unsigned short opcode;
+@@ -189,6 +190,7 @@ int is_valid_bugaddr(unsigned long pc)
+ 
+ 	return opcode == AVR32_BUG_OPCODE;
+ }
++#endif
+ 
+ asmlinkage void do_illegal_opcode(unsigned long ecr, struct pt_regs *regs)
+ {
+@@ -197,6 +199,7 @@ asmlinkage void do_illegal_opcode(unsigned long ecr, struct pt_regs *regs)
+ 	void __user *pc;
+ 	long code;
+ 
++#ifdef CONFIG_BUG
+ 	if (!user_mode(regs) && (ecr == ECR_ILLEGAL_OPCODE)) {
+ 		enum bug_trap_type type;
+ 
+@@ -211,6 +214,7 @@ asmlinkage void do_illegal_opcode(unsigned long ecr, struct pt_regs *regs)
+ 			die("Kernel BUG", regs, SIGKILL);
+ 		}
+ 	}
++#endif
+ 
+ 	local_irq_enable();
+ 
+diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig
+index 250958d..9d4bd22 100644
+--- a/arch/sparc64/defconfig
++++ b/arch/sparc64/defconfig
+@@ -1,7 +1,7 @@
+ #
+ # Automatically generated make config: don't edit
+-# Linux kernel version: 2.6.25-rc1
+-# Sun Feb 17 22:44:12 2008
++# Linux kernel version: 2.6.25-rc3
++# Wed Mar 26 04:33:35 2008
+ #
+ CONFIG_SPARC=y
+ CONFIG_SPARC64=y
+@@ -55,9 +55,11 @@ CONFIG_POSIX_MQUEUE=y
+ # CONFIG_IKCONFIG is not set
+ CONFIG_LOG_BUF_SHIFT=18
+ # CONFIG_CGROUPS is not set
++CONFIG_GROUP_SCHED=y
+ CONFIG_FAIR_GROUP_SCHED=y
+-CONFIG_FAIR_USER_SCHED=y
+-# CONFIG_FAIR_CGROUP_SCHED is not set
++CONFIG_RT_GROUP_SCHED=y
++CONFIG_USER_SCHED=y
++# CONFIG_CGROUP_SCHED is not set
+ CONFIG_SYSFS_DEPRECATED=y
+ CONFIG_RELAY=y
+ CONFIG_NAMESPACES=y
+@@ -482,6 +484,7 @@ CONFIG_SCSI_LOWLEVEL=y
+ # CONFIG_SCSI_IPS is not set
+ # CONFIG_SCSI_INITIO is not set
+ # CONFIG_SCSI_INIA100 is not set
++# CONFIG_SCSI_MVSAS is not set
+ # CONFIG_SCSI_STEX is not set
+ # CONFIG_SCSI_SYM53C8XX_2 is not set
+ # CONFIG_SCSI_QLOGIC_1280 is not set
+@@ -810,6 +813,7 @@ CONFIG_HWMON=y
+ # CONFIG_SENSORS_ADM1031 is not set
+ # CONFIG_SENSORS_ADM9240 is not set
+ # CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7473 is not set
+ # CONFIG_SENSORS_ATXP1 is not set
+ # CONFIG_SENSORS_DS1621 is not set
+ # CONFIG_SENSORS_I5K_AMB is not set
+diff --git a/arch/sparc64/kernel/cpu.c b/arch/sparc64/kernel/cpu.c
+index dd5d28e..0097c08 100644
+--- a/arch/sparc64/kernel/cpu.c
++++ b/arch/sparc64/kernel/cpu.c
+@@ -15,6 +15,8 @@
+ #include <asm/spitfire.h>
+ #include <asm/oplib.h>
+ 
++#include "entry.h"
++
+ DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 };
+ 
+ struct cpu_iu_info {
+@@ -65,8 +67,6 @@ static struct cpu_iu_info linux_sparc_chips[] = {
+ char *sparc_cpu_type;
+ char *sparc_fpu_type;
+ 
+-unsigned int fsr_storage;
+-
+ static void __init sun4v_cpu_probe(void)
+ {
+ 	switch (sun4v_chip_type) {
+@@ -94,8 +94,10 @@ void __init cpu_probe(void)
+ 	unsigned long ver, fpu_vers, manuf, impl, fprs;
+ 	int i;
+ 	
+-	if (tlb_type == hypervisor)
+-		return sun4v_cpu_probe();
++	if (tlb_type == hypervisor) {
++		sun4v_cpu_probe();
++		return;
++	}
+ 
+ 	fprs = fprs_read();
+ 	fprs_write(FPRS_FEF);
+diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S
+index 6be4d2d..49eca4b 100644
+--- a/arch/sparc64/kernel/entry.S
++++ b/arch/sparc64/kernel/entry.S
+@@ -1705,6 +1705,36 @@ __flushw_user:
+ 2:	retl
+ 	 nop
+ 
++	/* Flush %fp and %i7 to the stack for all register
++	 * windows active inside of the cpu.  This allows
++	 * show_stack_trace() to avoid using an expensive
++	 * 'flushw'.
++	 */
++	.globl		stack_trace_flush
++	.type		stack_trace_flush,#function
++stack_trace_flush:
++	rdpr		%pstate, %o0
++	wrpr		%o0, PSTATE_IE, %pstate
++
++	rdpr		%cwp, %g1
++	rdpr		%canrestore, %g2
++	sub		%g1, 1, %g3
++
++1:	brz,pn		%g2, 2f
++	 sub		%g2, 1, %g2
++	wrpr		%g3, %cwp
++	stx		%fp, [%sp + STACK_BIAS + RW_V9_I6]
++	stx		%i7, [%sp + STACK_BIAS + RW_V9_I7]
++	ba,pt		%xcc, 1b
++	 sub		%g3, 1, %g3
++
++2:	wrpr		%g1, %cwp
++	wrpr		%o0, %pstate
++
++	retl
++	 nop
++	.size		stack_trace_flush,.-stack_trace_flush
++
+ #ifdef CONFIG_SMP
+ 	.globl		hard_smp_processor_id
+ hard_smp_processor_id:
+diff --git a/arch/sparc64/kernel/entry.h b/arch/sparc64/kernel/entry.h
+new file mode 100644
+index 0000000..4a91e9c
+--- /dev/null
++++ b/arch/sparc64/kernel/entry.h
+@@ -0,0 +1,196 @@
++#ifndef _ENTRY_H
++#define _ENTRY_H
++
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/init.h>
++
++extern char *sparc_cpu_type;
++extern char *sparc_fpu_type;
++
++extern void __init per_cpu_patch(void);
++extern void __init sun4v_patch(void);
++extern void __init boot_cpu_id_too_large(int cpu);
++extern unsigned int dcache_parity_tl1_occurred;
++extern unsigned int icache_parity_tl1_occurred;
++
++extern asmlinkage void update_perfctrs(void);
++extern asmlinkage void sparc_breakpoint(struct pt_regs *regs);
++extern void timer_interrupt(int irq, struct pt_regs *regs);
++
++extern void do_notify_resume(struct pt_regs *regs,
++			     unsigned long orig_i0,
++			     int restart_syscall,
++			     unsigned long thread_info_flags);
++
++extern asmlinkage void syscall_trace(struct pt_regs *regs,
++				     int syscall_exit_p);
++
++extern void bad_trap_tl1(struct pt_regs *regs, long lvl);
++
++extern void do_fpe_common(struct pt_regs *regs);
++extern void do_fpieee(struct pt_regs *regs);
++extern void do_fpother(struct pt_regs *regs);
++extern void do_tof(struct pt_regs *regs);
++extern void do_div0(struct pt_regs *regs);
++extern void do_illegal_instruction(struct pt_regs *regs);
++extern void mem_address_unaligned(struct pt_regs *regs,
++				  unsigned long sfar,
++				  unsigned long sfsr);
++extern void sun4v_do_mna(struct pt_regs *regs,
++			 unsigned long addr,
++			 unsigned long type_ctx);
++extern void do_privop(struct pt_regs *regs);
++extern void do_privact(struct pt_regs *regs);
++extern void do_cee(struct pt_regs *regs);
++extern void do_cee_tl1(struct pt_regs *regs);
++extern void do_dae_tl1(struct pt_regs *regs);
++extern void do_iae_tl1(struct pt_regs *regs);
++extern void do_div0_tl1(struct pt_regs *regs);
++extern void do_fpdis_tl1(struct pt_regs *regs);
++extern void do_fpieee_tl1(struct pt_regs *regs);
++extern void do_fpother_tl1(struct pt_regs *regs);
++extern void do_ill_tl1(struct pt_regs *regs);
++extern void do_irq_tl1(struct pt_regs *regs);
++extern void do_lddfmna_tl1(struct pt_regs *regs);
++extern void do_stdfmna_tl1(struct pt_regs *regs);
++extern void do_paw(struct pt_regs *regs);
++extern void do_paw_tl1(struct pt_regs *regs);
++extern void do_vaw(struct pt_regs *regs);
++extern void do_vaw_tl1(struct pt_regs *regs);
++extern void do_tof_tl1(struct pt_regs *regs);
++extern void do_getpsr(struct pt_regs *regs);
++
++extern void spitfire_insn_access_exception(struct pt_regs *regs,
++					   unsigned long sfsr,
++					   unsigned long sfar);
++extern void spitfire_insn_access_exception_tl1(struct pt_regs *regs,
++					       unsigned long sfsr,
++					       unsigned long sfar);
++extern void spitfire_data_access_exception(struct pt_regs *regs,
++					   unsigned long sfsr,
++					   unsigned long sfar);
++extern void spitfire_data_access_exception_tl1(struct pt_regs *regs,
++					       unsigned long sfsr,
++					       unsigned long sfar);
++extern void spitfire_access_error(struct pt_regs *regs,
++				  unsigned long status_encoded,
++				  unsigned long afar);
++
++extern void cheetah_fecc_handler(struct pt_regs *regs,
++				 unsigned long afsr,
++				 unsigned long afar);
++extern void cheetah_cee_handler(struct pt_regs *regs,
++				unsigned long afsr,
++				unsigned long afar);
++extern void cheetah_deferred_handler(struct pt_regs *regs,
++				     unsigned long afsr,
++				     unsigned long afar);
++extern void cheetah_plus_parity_error(int type, struct pt_regs *regs);
++
++extern void sun4v_insn_access_exception(struct pt_regs *regs,
++					unsigned long addr,
++					unsigned long type_ctx);
++extern void sun4v_insn_access_exception_tl1(struct pt_regs *regs,
++					    unsigned long addr,
++					    unsigned long type_ctx);
++extern void sun4v_data_access_exception(struct pt_regs *regs,
++					unsigned long addr,
++					unsigned long type_ctx);
++extern void sun4v_data_access_exception_tl1(struct pt_regs *regs,
++					    unsigned long addr,
++					    unsigned long type_ctx);
++extern void sun4v_resum_error(struct pt_regs *regs,
++			      unsigned long offset);
++extern void sun4v_resum_overflow(struct pt_regs *regs);
++extern void sun4v_nonresum_error(struct pt_regs *regs,
++				 unsigned long offset);
++extern void sun4v_nonresum_overflow(struct pt_regs *regs);
++
++extern unsigned long sun4v_err_itlb_vaddr;
++extern unsigned long sun4v_err_itlb_ctx;
++extern unsigned long sun4v_err_itlb_pte;
++extern unsigned long sun4v_err_itlb_error;
++
++extern void sun4v_itlb_error_report(struct pt_regs *regs, int tl);
++
++extern unsigned long sun4v_err_dtlb_vaddr;
++extern unsigned long sun4v_err_dtlb_ctx;
++extern unsigned long sun4v_err_dtlb_pte;
++extern unsigned long sun4v_err_dtlb_error;
++
++extern void sun4v_dtlb_error_report(struct pt_regs *regs, int tl);
++extern void hypervisor_tlbop_error(unsigned long err,
++				   unsigned long op);
++extern void hypervisor_tlbop_error_xcall(unsigned long err,
++					 unsigned long op);
++
++/* WARNING: The error trap handlers in assembly know the precise
++ *	    layout of the following structure.
++ *
++ * C-level handlers in traps.c use this information to log the
++ * error and then determine how to recover (if possible).
++ */
++struct cheetah_err_info {
++/*0x00*/u64 afsr;
++/*0x08*/u64 afar;
++
++	/* D-cache state */
++/*0x10*/u64 dcache_data[4];	/* The actual data	*/
++/*0x30*/u64 dcache_index;	/* D-cache index	*/
++/*0x38*/u64 dcache_tag;		/* D-cache tag/valid	*/
++/*0x40*/u64 dcache_utag;	/* D-cache microtag	*/
++/*0x48*/u64 dcache_stag;	/* D-cache snooptag	*/
++
++	/* I-cache state */
++/*0x50*/u64 icache_data[8];	/* The actual insns + predecode	*/
++/*0x90*/u64 icache_index;	/* I-cache index	*/
++/*0x98*/u64 icache_tag;		/* I-cache phys tag	*/
++/*0xa0*/u64 icache_utag;	/* I-cache microtag	*/
++/*0xa8*/u64 icache_stag;	/* I-cache snooptag	*/
++/*0xb0*/u64 icache_upper;	/* I-cache upper-tag	*/
++/*0xb8*/u64 icache_lower;	/* I-cache lower-tag	*/
++
++	/* E-cache state */
++/*0xc0*/u64 ecache_data[4];	/* 32 bytes from staging registers */
++/*0xe0*/u64 ecache_index;	/* E-cache index	*/
++/*0xe8*/u64 ecache_tag;		/* E-cache tag/state	*/
++
++/*0xf0*/u64 __pad[32 - 30];
++};
++#define CHAFSR_INVALID		((u64)-1L)
++
++/* This is allocated at boot time based upon the largest hardware
++ * cpu ID in the system.  We allocate two entries per cpu, one for
++ * TL==0 logging and one for TL >= 1 logging.
++ */
++extern struct cheetah_err_info *cheetah_error_log;
++
++/* UPA nodes send interrupt packet to UltraSparc with first data reg
++ * value low 5 (7 on Starfire) bits holding the IRQ identifier being
++ * delivered.  We must translate this into a non-vector IRQ so we can
++ * set the softint on this cpu.
++ *
++ * To make processing these packets efficient and race free we use
++ * an array of irq buckets below.  The interrupt vector handler in
++ * entry.S feeds incoming packets into per-cpu pil-indexed lists.
++ *
++ * If you make changes to ino_bucket, please update hand coded assembler
++ * of the vectored interrupt trap handler(s) in entry.S and sun4v_ivec.S
++ */
++struct ino_bucket {
++/*0x00*/unsigned long __irq_chain_pa;
++
++	/* Virtual interrupt number assigned to this INO.  */
++/*0x08*/unsigned int __virt_irq;
++/*0x0c*/unsigned int __pad;
++};
++
++extern struct ino_bucket *ivector_table;
++extern unsigned long ivector_table_pa;
++
++extern void handler_irq(int irq, struct pt_regs *regs);
++extern void init_irqwork_curcpu(void);
++extern void __cpuinit sun4v_register_mondo_queues(int this_cpu);
++
++#endif /* _ENTRY_H */
+diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c
+index fbaab34..b781d3d 100644
+--- a/arch/sparc64/kernel/iommu.c
++++ b/arch/sparc64/kernel/iommu.c
+@@ -626,7 +626,7 @@ static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
+ iommu_map_failed:
+ 	for_each_sg(sglist, s, nelems, i) {
+ 		if (s->dma_length != 0) {
+-			unsigned long vaddr, npages, entry, i;
++			unsigned long vaddr, npages, entry, j;
+ 			iopte_t *base;
+ 
+ 			vaddr = s->dma_address & IO_PAGE_MASK;
+@@ -637,8 +637,8 @@ iommu_map_failed:
+ 				>> IO_PAGE_SHIFT;
+ 			base = iommu->page_table + entry;
+ 
+-			for (i = 0; i < npages; i++)
+-				iopte_make_dummy(iommu, base + i);
++			for (j = 0; j < npages; j++)
++				iopte_make_dummy(iommu, base + j);
+ 
+ 			s->dma_address = DMA_ERROR_CODE;
+ 			s->dma_length = 0;
+@@ -803,7 +803,7 @@ static void dma_4u_sync_sg_for_cpu(struct device *dev,
+ 	spin_unlock_irqrestore(&iommu->lock, flags);
+ }
+ 
+-const struct dma_ops sun4u_dma_ops = {
++static const struct dma_ops sun4u_dma_ops = {
+ 	.alloc_coherent		= dma_4u_alloc_coherent,
+ 	.free_coherent		= dma_4u_free_coherent,
+ 	.map_single		= dma_4u_map_single,
+diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c
+index 5ec06c8..eb88bd6 100644
+--- a/arch/sparc64/kernel/irq.c
++++ b/arch/sparc64/kernel/irq.c
+@@ -44,27 +44,10 @@
+ #include <asm/hypervisor.h>
+ #include <asm/cacheflush.h>
+ 
+-/* UPA nodes send interrupt packet to UltraSparc with first data reg
+- * value low 5 (7 on Starfire) bits holding the IRQ identifier being
+- * delivered.  We must translate this into a non-vector IRQ so we can
+- * set the softint on this cpu.
+- *
+- * To make processing these packets efficient and race free we use
+- * an array of irq buckets below.  The interrupt vector handler in
+- * entry.S feeds incoming packets into per-cpu pil-indexed lists.
+- *
+- * If you make changes to ino_bucket, please update hand coded assembler
+- * of the vectored interrupt trap handler(s) in entry.S and sun4v_ivec.S
+- */
+-struct ino_bucket {
+-/*0x00*/unsigned long __irq_chain_pa;
+-
+-	/* Virtual interrupt number assigned to this INO.  */
+-/*0x08*/unsigned int __virt_irq;
+-/*0x0c*/unsigned int __pad;
+-};
++#include "entry.h"
+ 
+ #define NUM_IVECS	(IMAP_INR + 1)
++
+ struct ino_bucket *ivector_table;
+ unsigned long ivector_table_pa;
+ 
+diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c
+index 9a1ba1f..aaae865 100644
+--- a/arch/sparc64/kernel/ptrace.c
++++ b/arch/sparc64/kernel/ptrace.c
+@@ -35,6 +35,9 @@
+ #include <asm/spitfire.h>
+ #include <asm/page.h>
+ #include <asm/cpudata.h>
++#include <asm/cacheflush.h>
++
++#include "entry.h"
+ 
+ /* #define ALLOW_INIT_TRACING */
+ 
+@@ -67,6 +70,8 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
+ 	if (tlb_type == hypervisor)
+ 		return;
+ 
++	preempt_disable();
++
+ #ifdef DCACHE_ALIASING_POSSIBLE
+ 	/* If bit 13 of the kernel address we used to access the
+ 	 * user page is the same as the virtual address that page
+@@ -105,6 +110,8 @@ void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
+ 		for (; start < end; start += icache_line_size)
+ 			flushi(start);
+ 	}
++
++	preempt_enable();
+ }
+ 
+ enum sparc_regset {
+@@ -382,6 +389,7 @@ static const struct user_regset_view user_sparc64_view = {
+ 	.regsets = sparc64_regsets, .n = ARRAY_SIZE(sparc64_regsets)
+ };
+ 
++#ifdef CONFIG_COMPAT
+ static int genregs32_get(struct task_struct *target,
+ 			 const struct user_regset *regset,
+ 			 unsigned int pos, unsigned int count,
+@@ -676,14 +684,18 @@ static const struct user_regset_view user_sparc32_view = {
+ 	.name = "sparc", .e_machine = EM_SPARC,
+ 	.regsets = sparc32_regsets, .n = ARRAY_SIZE(sparc32_regsets)
+ };
++#endif /* CONFIG_COMPAT */
+ 
+ const struct user_regset_view *task_user_regset_view(struct task_struct *task)
+ {
++#ifdef CONFIG_COMPAT
+ 	if (test_tsk_thread_flag(task, TIF_32BIT))
+ 		return &user_sparc32_view;
++#endif
+ 	return &user_sparc64_view;
+ }
+ 
++#ifdef CONFIG_COMPAT
+ struct compat_fps {
+ 	unsigned int regs[32];
+ 	unsigned int fsr;
+@@ -798,6 +810,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
+ 
+ 	return ret;
+ }
++#endif /* CONFIG_COMPAT */
+ 
+ struct fps {
+ 	unsigned int regs[64];
+@@ -807,11 +820,14 @@ struct fps {
+ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
+ {
+ 	const struct user_regset_view *view = task_user_regset_view(child);
+-	struct pt_regs __user *pregs = (struct pt_regs __user *) addr;
+ 	unsigned long addr2 = task_pt_regs(current)->u_regs[UREG_I4];
+-	struct fps __user *fps = (struct fps __user *) addr;
++	struct pt_regs __user *pregs;
++	struct fps __user *fps;
+ 	int ret;
+ 
++	pregs = (struct pt_regs __user *) (unsigned long) addr;
++	fps = (struct fps __user *) (unsigned long) addr;
++
+ 	switch (request) {
+ 	case PTRACE_PEEKUSR:
+ 		ret = (addr != 0) ? -EIO : 0;
+diff --git a/arch/sparc64/kernel/setup.c b/arch/sparc64/kernel/setup.c
+index d036dbe..6acb4c5 100644
+--- a/arch/sparc64/kernel/setup.c
++++ b/arch/sparc64/kernel/setup.c
+@@ -51,6 +51,8 @@
+ #include <net/ipconfig.h>
+ #endif
+ 
++#include "entry.h"
++
+ /* Used to synchronize accesses to NatSemi SUPER I/O chip configure
+  * operations in asm/ns87303.h
+  */
+@@ -335,9 +337,6 @@ void __init setup_arch(char **cmdline_p)
+ 
+ /* BUFFER is PAGE_SIZE bytes long. */
+ 
+-extern char *sparc_cpu_type;
+-extern char *sparc_fpu_type;
+-
+ extern void smp_info(struct seq_file *);
+ extern void smp_bogo(struct seq_file *);
+ extern void mmu_info(struct seq_file *);
+diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c
+index fb13775..94a9d64 100644
+--- a/arch/sparc64/kernel/signal.c
++++ b/arch/sparc64/kernel/signal.c
+@@ -32,6 +32,9 @@
+ #include <asm/siginfo.h>
+ #include <asm/visasm.h>
+ 
++#include "entry.h"
++#include "systbls.h"
++
+ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+ 
+ /* {set, get}context() needed for 64-bit SparcLinux userland. */
+diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c
+index 5a1126b..59f020d 100644
+--- a/arch/sparc64/kernel/smp.c
++++ b/arch/sparc64/kernel/smp.c
+@@ -1,6 +1,6 @@
+ /* smp.c: Sparc64 SMP support.
+  *
+- * Copyright (C) 1997, 2007 David S. Miller (davem at davemloft.net)
++ * Copyright (C) 1997, 2007, 2008 David S. Miller (davem at davemloft.net)
+  */
+ 
+ #include <linux/module.h>
+@@ -30,6 +30,7 @@
+ #include <asm/cpudata.h>
+ #include <asm/hvtramp.h>
+ #include <asm/io.h>
++#include <asm/timer.h>
+ 
+ #include <asm/irq.h>
+ #include <asm/irq_regs.h>
+diff --git a/arch/sparc64/kernel/stacktrace.c b/arch/sparc64/kernel/stacktrace.c
+index 47f92a5..84d39e8 100644
+--- a/arch/sparc64/kernel/stacktrace.c
++++ b/arch/sparc64/kernel/stacktrace.c
+@@ -2,13 +2,15 @@
+ #include <linux/stacktrace.h>
+ #include <linux/thread_info.h>
+ #include <asm/ptrace.h>
++#include <asm/stacktrace.h>
+ 
+ void save_stack_trace(struct stack_trace *trace)
+ {
+ 	unsigned long ksp, fp, thread_base;
+ 	struct thread_info *tp = task_thread_info(current);
+ 
+-	flushw_all();
++	stack_trace_flush();
++
+ 	__asm__ __volatile__(
+ 		"mov	%%fp, %0"
+ 		: "=r" (ksp)
+diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c
+index 134d801..f952745 100644
+--- a/arch/sparc64/kernel/sys_sparc.c
++++ b/arch/sparc64/kernel/sys_sparc.c
+@@ -1,5 +1,4 @@
+-/* $Id: sys_sparc.c,v 1.57 2002/02/09 19:49:30 davem Exp $
+- * linux/arch/sparc64/kernel/sys_sparc.c
++/* linux/arch/sparc64/kernel/sys_sparc.c
+  *
+  * This file contains various random system calls that
+  * have a non-standard calling sequence on the Linux/sparc
+@@ -30,6 +29,9 @@
+ #include <asm/perfctr.h>
+ #include <asm/unistd.h>
+ 
++#include "entry.h"
++#include "systbls.h"
++
+ /* #define DEBUG_UNIMP_SYSCALL */
+ 
+ asmlinkage unsigned long sys_getpagesize(void)
+@@ -445,7 +447,8 @@ asmlinkage long sys_ipc(unsigned int call, int first, unsigned long second,
+ 			goto out;
+ 		case SEMTIMEDOP:
+ 			err = sys_semtimedop(first, ptr, (unsigned)second,
+-				(const struct timespec __user *) fifth);
++				(const struct timespec __user *)
++					     (unsigned long) fifth);
+ 			goto out;
+ 		case SEMGET:
+ 			err = sys_semget(first, (int)second, (int)third);
+@@ -788,7 +791,7 @@ asmlinkage long sys_utrap_install(utrap_entry_t type,
+ 	} else {
+ 		if ((utrap_handler_t)current_thread_info()->utraps[type] != new_p &&
+ 		    current_thread_info()->utraps[0] > 1) {
+-			long *p = current_thread_info()->utraps;
++			unsigned long *p = current_thread_info()->utraps;
+ 
+ 			current_thread_info()->utraps =
+ 				kmalloc((UT_TRAP_INSTRUCTION_31+1)*sizeof(long),
+@@ -816,7 +819,8 @@ asmlinkage long sys_utrap_install(utrap_entry_t type,
+ 	return 0;
+ }
+ 
+-long sparc_memory_ordering(unsigned long model, struct pt_regs *regs)
++asmlinkage long sparc_memory_ordering(unsigned long model,
++				      struct pt_regs *regs)
+ {
+ 	if (model >= 3)
+ 		return -EINVAL;
+diff --git a/arch/sparc64/kernel/systbls.h b/arch/sparc64/kernel/systbls.h
+new file mode 100644
+index 0000000..8a0d20a
+--- /dev/null
++++ b/arch/sparc64/kernel/systbls.h
+@@ -0,0 +1,53 @@
++#ifndef _SYSTBLS_H
++#define _SYSTBLS_H
++
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/utsname.h>
++#include <asm/utrap.h>
++#include <asm/signal.h>
++
++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,
++			       unsigned long third,
++			       void __user *ptr, long fifth);
++extern asmlinkage long sparc64_newuname(struct new_utsname __user *name);
++extern asmlinkage long sparc64_personality(unsigned long personality);
++extern asmlinkage unsigned long sys_mmap(unsigned long addr, unsigned long len,
++					 unsigned long prot, unsigned long flags,
++					 unsigned long fd, unsigned long off);
++extern asmlinkage long sys64_munmap(unsigned long addr, size_t len);
++extern asmlinkage unsigned long sys64_mremap(unsigned long addr,
++					     unsigned long old_len,
++					     unsigned long new_len,
++					     unsigned long flags,
++					     unsigned long new_addr);
++extern asmlinkage unsigned long c_sys_nis_syscall(struct pt_regs *regs);
++extern asmlinkage long sys_getdomainname(char __user *name, int len);
++extern asmlinkage long solaris_syscall(struct pt_regs *regs);
++extern asmlinkage long sunos_syscall(struct pt_regs *regs);
++extern asmlinkage long sys_utrap_install(utrap_entry_t type,
++					 utrap_handler_t new_p,
++					 utrap_handler_t new_d,
++					 utrap_handler_t __user *old_p,
++					 utrap_handler_t __user *old_d);
++extern asmlinkage long sparc_memory_ordering(unsigned long model,
++					     struct pt_regs *regs);
++extern asmlinkage long sys_rt_sigaction(int sig,
++					const struct sigaction __user *act,
++					struct sigaction __user *oact,
++					void __user *restorer,
++					size_t sigsetsize);
++extern asmlinkage long sys_perfctr(int opcode, unsigned long arg0,
++				   unsigned long arg1, unsigned long arg2);
++
++extern asmlinkage void sparc64_set_context(struct pt_regs *regs);
++extern asmlinkage void sparc64_get_context(struct pt_regs *regs);
++extern asmlinkage long sys_sigpause(unsigned int set);
++extern asmlinkage long sys_sigsuspend(old_sigset_t set);
++extern void do_rt_sigreturn(struct pt_regs *regs);
++
++#endif /* _SYSTBLS_H */
+diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c
+index d204f1a..e5d2389 100644
+--- a/arch/sparc64/kernel/time.c
++++ b/arch/sparc64/kernel/time.c
+@@ -1,7 +1,6 @@
+-/* $Id: time.c,v 1.42 2002/01/23 14:33:55 davem Exp $
+- * time.c: UltraSparc timer and TOD clock support.
++/* time.c: UltraSparc timer and TOD clock support.
+  *
+- * Copyright (C) 1997 David S. Miller (davem at caip.rutgers.edu)
++ * Copyright (C) 1997, 2008 David S. Miller (davem at davemloft.net)
+  * Copyright (C) 1998 Eddie C. Dost   (ecd at skynet.be)
+  *
+  * Based largely on code which is:
+@@ -48,6 +47,8 @@
+ #include <asm/uaccess.h>
+ #include <asm/irq_regs.h>
+ 
++#include "entry.h"
++
+ DEFINE_SPINLOCK(mostek_lock);
+ DEFINE_SPINLOCK(rtc_lock);
+ void __iomem *mstk48t02_regs = NULL;
+@@ -508,6 +509,37 @@ static int __init has_low_battery(void)
+ 	return (data1 == data2);	/* Was the write blocked? */
+ }
+ 
++static void __init mostek_set_system_time(void __iomem *mregs)
++{
++	unsigned int year, mon, day, hour, min, sec;
++	u8 tmp;
++
++	spin_lock_irq(&mostek_lock);
++
++	/* Traditional Mostek chip. */
++	tmp = mostek_read(mregs + MOSTEK_CREG);
++	tmp |= MSTK_CREG_READ;
++	mostek_write(mregs + MOSTEK_CREG, tmp);
++
++	sec = MSTK_REG_SEC(mregs);
++	min = MSTK_REG_MIN(mregs);
++	hour = MSTK_REG_HOUR(mregs);
++	day = MSTK_REG_DOM(mregs);
++	mon = MSTK_REG_MONTH(mregs);
++	year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) );
++
++	xtime.tv_sec = mktime(year, mon, day, hour, min, sec);
++	xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
++	set_normalized_timespec(&wall_to_monotonic,
++ 	                        -xtime.tv_sec, -xtime.tv_nsec);
++
++	tmp = mostek_read(mregs + MOSTEK_CREG);
++	tmp &= ~MSTK_CREG_READ;
++	mostek_write(mregs + MOSTEK_CREG, tmp);
++
++	spin_unlock_irq(&mostek_lock);
++}
++
+ /* Probe for the real time clock chip. */
+ static void __init set_system_time(void)
+ {
+@@ -520,7 +552,6 @@ static void __init set_system_time(void)
+ 	unsigned long dregs = 0UL;
+ 	void __iomem *bregs = 0UL;
+ #endif
+-	u8 tmp;
+ 
+ 	if (!mregs && !dregs && !bregs) {
+ 		prom_printf("Something wrong, clock regs not mapped yet.\n");
+@@ -528,20 +559,11 @@ static void __init set_system_time(void)
+ 	}		
+ 
+ 	if (mregs) {
+-		spin_lock_irq(&mostek_lock);
+-
+-		/* Traditional Mostek chip. */
+-		tmp = mostek_read(mregs + MOSTEK_CREG);
+-		tmp |= MSTK_CREG_READ;
+-		mostek_write(mregs + MOSTEK_CREG, tmp);
++		mostek_set_system_time(mregs);
++		return;
++	}
+ 
+-		sec = MSTK_REG_SEC(mregs);
+-		min = MSTK_REG_MIN(mregs);
+-		hour = MSTK_REG_HOUR(mregs);
+-		day = MSTK_REG_DOM(mregs);
+-		mon = MSTK_REG_MONTH(mregs);
+-		year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) );
+-	} else if (bregs) {
++	if (bregs) {
+ 		unsigned char val = readb(bregs + 0x0e);
+ 		unsigned int century;
+ 
+@@ -596,14 +618,6 @@ static void __init set_system_time(void)
+ 	xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ);
+ 	set_normalized_timespec(&wall_to_monotonic,
+  	                        -xtime.tv_sec, -xtime.tv_nsec);
+-
+-	if (mregs) {
+-		tmp = mostek_read(mregs + MOSTEK_CREG);
+-		tmp &= ~MSTK_CREG_READ;
+-		mostek_write(mregs + MOSTEK_CREG, tmp);
+-
+-		spin_unlock_irq(&mostek_lock);
+-	}
+ }
+ 
+ /* davem suggests we keep this within the 4M locked kernel image */
+@@ -1027,7 +1041,7 @@ void __init time_init(void)
+ 	setup_clockevent_multiplier(clock);
+ 
+ 	sparc64_clockevent.max_delta_ns =
+-		clockevent_delta2ns(0x7fffffffffffffff, &sparc64_clockevent);
++		clockevent_delta2ns(0x7fffffffffffffffUL, &sparc64_clockevent);
+ 	sparc64_clockevent.min_delta_ns =
+ 		clockevent_delta2ns(0xF, &sparc64_clockevent);
+ 
+diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
+index 007f531..96da847 100644
+--- a/arch/sparc64/kernel/traps.c
++++ b/arch/sparc64/kernel/traps.c
+@@ -42,6 +42,7 @@
+ #endif
+ #include <asm/prom.h>
+ 
++#include "entry.h"
+ 
+ /* When an irrecoverable trap occurs at tl > 0, the trap entry
+  * code logs the trap state registers at every level in the trap
+@@ -77,11 +78,6 @@ static void dump_tl1_traplog(struct tl1_traplog *p)
+ 	}
+ }
+ 
+-void do_call_debug(struct pt_regs *regs) 
+-{ 
+-	notify_die(DIE_CALL, "debug call", regs, 0, 255, SIGINT); 
+-}
+-
+ void bad_trap(struct pt_regs *regs, long lvl)
+ {
+ 	char buffer[32];
+@@ -550,41 +546,6 @@ static unsigned long ecache_flush_physbase;
+ static unsigned long ecache_flush_linesize;
+ static unsigned long ecache_flush_size;
+ 
+-/* WARNING: The error trap handlers in assembly know the precise
+- *	    layout of the following structure.
+- *
+- * C-level handlers below use this information to log the error
+- * and then determine how to recover (if possible).
+- */
+-struct cheetah_err_info {
+-/*0x00*/u64 afsr;
+-/*0x08*/u64 afar;
+-
+-	/* D-cache state */
+-/*0x10*/u64 dcache_data[4];	/* The actual data	*/
+-/*0x30*/u64 dcache_index;	/* D-cache index	*/
+-/*0x38*/u64 dcache_tag;		/* D-cache tag/valid	*/
+-/*0x40*/u64 dcache_utag;	/* D-cache microtag	*/
+-/*0x48*/u64 dcache_stag;	/* D-cache snooptag	*/
+-
+-	/* I-cache state */
+-/*0x50*/u64 icache_data[8];	/* The actual insns + predecode	*/
+-/*0x90*/u64 icache_index;	/* I-cache index	*/
+-/*0x98*/u64 icache_tag;		/* I-cache phys tag	*/
+-/*0xa0*/u64 icache_utag;	/* I-cache microtag	*/
+-/*0xa8*/u64 icache_stag;	/* I-cache snooptag	*/
+-/*0xb0*/u64 icache_upper;	/* I-cache upper-tag	*/
+-/*0xb8*/u64 icache_lower;	/* I-cache lower-tag	*/
+-
+-	/* E-cache state */
+-/*0xc0*/u64 ecache_data[4];	/* 32 bytes from staging registers */
+-/*0xe0*/u64 ecache_index;	/* E-cache index	*/
+-/*0xe8*/u64 ecache_tag;		/* E-cache tag/state	*/
+-
+-/*0xf0*/u64 __pad[32 - 30];
+-};
+-#define CHAFSR_INVALID		((u64)-1L)
+-
+ /* This table is ordered in priority of errors and matches the
+  * AFAR overwrite policy as well.
+  */
+@@ -758,10 +719,6 @@ static struct afsr_error_table __jalapeno_error_table[] = {
+ static struct afsr_error_table *cheetah_error_table;
+ static unsigned long cheetah_afsr_errors;
+ 
+-/* This is allocated at boot time based upon the largest hardware
+- * cpu ID in the system.  We allocate two entries per cpu, one for
+- * TL==0 logging and one for TL >= 1 logging.
+- */
+ struct cheetah_err_info *cheetah_error_log;
+ 
+ static inline struct cheetah_err_info *cheetah_get_error_log(unsigned long afsr)
+@@ -2102,7 +2059,7 @@ void do_div0(struct pt_regs *regs)
+ 	force_sig_info(SIGFPE, &info, current);
+ }
+ 
+-void instruction_dump (unsigned int *pc)
++static void instruction_dump(unsigned int *pc)
+ {
+ 	int i;
+ 
+@@ -2115,7 +2072,7 @@ void instruction_dump (unsigned int *pc)
+ 	printk("\n");
+ }
+ 
+-static void user_instruction_dump (unsigned int __user *pc)
++static void user_instruction_dump(unsigned int __user *pc)
+ {
+ 	int i;
+ 	unsigned int buf[9];
+diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
+index 466fd6c..f37078d 100644
+--- a/arch/sparc64/mm/init.c
++++ b/arch/sparc64/mm/init.c
+@@ -46,6 +46,7 @@
+ #include <asm/prom.h>
+ #include <asm/sstate.h>
+ #include <asm/mdesc.h>
++#include <asm/cpudata.h>
+ 
+ #define MAX_PHYS_ADDRESS	(1UL << 42UL)
+ #define KPTE_BITMAP_CHUNK_SZ	(256UL * 1024UL * 1024UL)
+@@ -1273,10 +1274,6 @@ void __cpuinit sun4v_ktsb_register(void)
+ 
+ /* paging_init() sets up the page tables */
+ 
+-extern void cheetah_ecache_flush_init(void);
+-extern void sun4v_patch_tlb_handlers(void);
+-
+-extern void cpu_probe(void);
+ extern void central_probe(void);
+ 
+ static unsigned long last_valid_pfn;
+diff --git a/arch/sparc64/mm/tlb.c b/arch/sparc64/mm/tlb.c
+index 3f10fc9..a0f000b 100644
+--- a/arch/sparc64/mm/tlb.c
++++ b/arch/sparc64/mm/tlb.c
+@@ -23,10 +23,11 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers) = { 0, };
+ 
+ void flush_tlb_pending(void)
+ {
+-	struct mmu_gather *mp = &__get_cpu_var(mmu_gathers);
++	struct mmu_gather *mp;
+ 
+ 	preempt_disable();
+ 
++	mp = &__get_cpu_var(mmu_gathers);
+ 	if (mp->tlb_nr) {
+ 		flush_tsb_user(mp);
+ 
+diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
+index 1e8f41a..1d43bdf 100644
+--- a/arch/um/drivers/net_kern.c
++++ b/arch/um/drivers/net_kern.c
+@@ -256,11 +256,7 @@ static struct net_device_stats *uml_net_get_stats(struct net_device *dev)
+ 
+ static void uml_net_set_multicast_list(struct net_device *dev)
+ {
+-	if (dev->flags & IFF_PROMISC)
+-		return;
+-	else if (dev->mc_count)
+-		dev->flags |= IFF_ALLMULTI;
+-	else dev->flags &= ~IFF_ALLMULTI;
++	return;
+ }
+ 
+ static void uml_net_tx_timeout(struct net_device *dev)
+diff --git a/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c b/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c
+index f2b5a62..8a85c93 100644
+--- a/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c
++++ b/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c
+@@ -63,7 +63,7 @@ static struct cpufreq_frequency_table speedstep_freqs[] = {
+  */
+ static int speedstep_smi_ownership (void)
+ {
+-	u32 command, result, magic;
++	u32 command, result, magic, dummy;
+ 	u32 function = GET_SPEEDSTEP_OWNER;
+ 	unsigned char magic_data[] = "Copyright (c) 1999 Intel Corporation";
+ 
+@@ -73,8 +73,11 @@ static int speedstep_smi_ownership (void)
+ 	dprintk("trying to obtain ownership with command %x at port %x\n", command, smi_port);
+ 
+ 	__asm__ __volatile__(
++		"push %%ebp\n"
+ 		"out %%al, (%%dx)\n"
+-		: "=D" (result)
++		"pop %%ebp\n"
++		: "=D" (result), "=a" (dummy), "=b" (dummy), "=c" (dummy), "=d" (dummy),
++			"=S" (dummy)
+ 		: "a" (command), "b" (function), "c" (0), "d" (smi_port),
+ 			"D" (0), "S" (magic)
+ 		: "memory"
+@@ -96,7 +99,7 @@ static int speedstep_smi_ownership (void)
+  */
+ static int speedstep_smi_get_freqs (unsigned int *low, unsigned int *high)
+ {
+-	u32 command, result = 0, edi, high_mhz, low_mhz;
++	u32 command, result = 0, edi, high_mhz, low_mhz, dummy;
+ 	u32 state=0;
+ 	u32 function = GET_SPEEDSTEP_FREQS;
+ 
+@@ -109,10 +112,12 @@ static int speedstep_smi_get_freqs (unsigned int *low, unsigned int *high)
+ 
+ 	dprintk("trying to determine frequencies with command %x at port %x\n", command, smi_port);
+ 
+-	__asm__ __volatile__("movl $0, %%edi\n"
++	__asm__ __volatile__(
++		"push %%ebp\n"
+ 		"out %%al, (%%dx)\n"
+-		: "=a" (result), "=b" (high_mhz), "=c" (low_mhz), "=d" (state), "=D" (edi)
+-		: "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0)
++		"pop %%ebp"
++		: "=a" (result), "=b" (high_mhz), "=c" (low_mhz), "=d" (state), "=D" (edi), "=S" (dummy)
++		: "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0), "D" (0)
+ 	);
+ 
+ 	dprintk("result %x, low_freq %u, high_freq %u\n", result, low_mhz, high_mhz);
+@@ -135,16 +140,18 @@ static int speedstep_smi_get_freqs (unsigned int *low, unsigned int *high)
+ static int speedstep_get_state (void)
+ {
+ 	u32 function=GET_SPEEDSTEP_STATE;
+-	u32 result, state, edi, command;
++	u32 result, state, edi, command, dummy;
+ 
+ 	command = (smi_sig & 0xffffff00) | (smi_cmd & 0xff);
+ 
+ 	dprintk("trying to determine current setting with command %x at port %x\n", command, smi_port);
+ 
+-	__asm__ __volatile__("movl $0, %%edi\n"
++	__asm__ __volatile__(
++		"push %%ebp\n"
+ 		"out %%al, (%%dx)\n"
+-		: "=a" (result), "=b" (state), "=D" (edi)
+-		: "a" (command), "b" (function), "c" (0), "d" (smi_port), "S" (0)
++		"pop %%ebp\n"
++		: "=a" (result), "=b" (state), "=D" (edi), "=c" (dummy), "=d" (dummy), "=S" (dummy)
++		: "a" (command), "b" (function), "c" (0), "d" (smi_port), "S" (0), "D" (0)
+ 	);
+ 
+ 	dprintk("state is %x, result is %x\n", state, result);
+@@ -160,7 +167,7 @@ static int speedstep_get_state (void)
+  */
+ static void speedstep_set_state (unsigned int state)
+ {
+-	unsigned int result = 0, command, new_state;
++	unsigned int result = 0, command, new_state, dummy;
+ 	unsigned long flags;
+ 	unsigned int function=SET_SPEEDSTEP_STATE;
+ 	unsigned int retry = 0;
+@@ -182,10 +189,12 @@ static void speedstep_set_state (unsigned int state)
+ 		}
+ 		retry++;
+ 		__asm__ __volatile__(
+-			"movl $0, %%edi\n"
++			"push %%ebp\n"
+ 			"out %%al, (%%dx)\n"
+-			: "=b" (new_state), "=D" (result)
+-			: "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0)
++			"pop %%ebp"
++			: "=b" (new_state), "=D" (result), "=c" (dummy), "=a" (dummy),
++				"=d" (dummy), "=S" (dummy)
++			: "a" (command), "b" (function), "c" (state), "d" (smi_port), "S" (0), "D" (0)
+ 			);
+ 	} while ((new_state != state) && (retry <= SMI_TRIES));
+ 
+@@ -195,7 +204,7 @@ static void speedstep_set_state (unsigned int state)
+ 	if (new_state == state) {
+ 		dprintk("change to %u MHz succeeded after %u tries with result %u\n", (speedstep_freqs[new_state].frequency / 1000), retry, result);
+ 	} else {
+-		printk(KERN_ERR "cpufreq: change failed with new_state %u and result %u\n", new_state, result);
++		printk(KERN_ERR "cpufreq: change to state %u failed with new_state %u and result %u\n", state, new_state, result);
+ 	}
+ 
+ 	return;
+diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c
+index 103d61a..3e18db4 100644
+--- a/arch/x86/kernel/cpu/mtrr/generic.c
++++ b/arch/x86/kernel/cpu/mtrr/generic.c
+@@ -176,12 +176,13 @@ static inline void k8_enable_fixed_iorrs(void)
+ }
+ 
+ /**
+- * Checks and updates an fixed-range MTRR if it differs from the value it
+- * should have. If K8 extentions are wanted, update the K8 SYSCFG MSR also.
+- * see AMD publication no. 24593, chapter 7.8.1, page 233 for more information
+- * \param msr MSR address of the MTTR which should be checked and updated
+- * \param changed pointer which indicates whether the MTRR needed to be changed
+- * \param msrwords pointer to the MSR values which the MSR should have
++ * set_fixed_range - checks & updates a fixed-range MTRR if it differs from the value it should have
++ * @msr: MSR address of the MTTR which should be checked and updated
++ * @changed: pointer which indicates whether the MTRR needed to be changed
++ * @msrwords: pointer to the MSR values which the MSR should have
++ *
++ * If K8 extentions are wanted, update the K8 SYSCFG MSR also.
++ * See AMD publication no. 24593, chapter 7.8.1, page 233 for more information.
+  */
+ static void set_fixed_range(int msr, bool *changed, unsigned int *msrwords)
+ {
+@@ -199,12 +200,15 @@ static void set_fixed_range(int msr, bool *changed, unsigned int *msrwords)
+ 	}
+ }
+ 
++/**
++ * generic_get_free_region - Get a free MTRR.
++ * @base: The starting (base) address of the region.
++ * @size: The size (in bytes) of the region.
++ * @replace_reg: mtrr index to be replaced; set to invalid value if none.
++ *
++ * Returns: The index of the region on success, else negative on error.
++ */
+ int generic_get_free_region(unsigned long base, unsigned long size, int replace_reg)
+-/*  [SUMMARY] Get a free MTRR.
+-    <base> The starting (base) address of the region.
+-    <size> The size (in bytes) of the region.
+-    [RETURNS] The index of the region on success, else -1 on error.
+-*/
+ {
+ 	int i, max;
+ 	mtrr_type ltype;
+@@ -249,8 +253,8 @@ static void generic_get_mtrr(unsigned int reg, unsigned long *base,
+ }
+ 
+ /**
+- * Checks and updates the fixed-range MTRRs if they differ from the saved set
+- * \param frs pointer to fixed-range MTRR values, saved by get_fixed_ranges()
++ * set_fixed_ranges - checks & updates the fixed-range MTRRs if they differ from the saved set
++ * @frs: pointer to fixed-range MTRR values, saved by get_fixed_ranges()
+  */
+ static int set_fixed_ranges(mtrr_type * frs)
+ {
+@@ -294,13 +298,13 @@ static bool set_mtrr_var_ranges(unsigned int index, struct mtrr_var_range *vr)
+ 
+ static u32 deftype_lo, deftype_hi;
+ 
++/**
++ * set_mtrr_state - Set the MTRR state for this CPU.
++ *
++ * NOTE: The CPU must already be in a safe state for MTRR changes.
++ * RETURNS: 0 if no changes made, else a mask indicating what was changed.
++ */
+ static unsigned long set_mtrr_state(void)
+-/*  [SUMMARY] Set the MTRR state for this CPU.
+-    <state> The MTRR state information to read.
+-    <ctxt> Some relevant CPU context.
+-    [NOTE] The CPU must already be in a safe state for MTRR changes.
+-    [RETURNS] 0 if no changes made, else a mask indication what was changed.
+-*/
+ {
+ 	unsigned int i;
+ 	unsigned long change_mask = 0;
+diff --git a/arch/x86/kernel/io_delay.c b/arch/x86/kernel/io_delay.c
+index c706a30..5921e5f 100644
+--- a/arch/x86/kernel/io_delay.c
++++ b/arch/x86/kernel/io_delay.c
+@@ -78,6 +78,14 @@ static struct dmi_system_id __initdata io_delay_0xed_port_dmi_table[] = {
+ 	},
+ 	{
+ 		.callback	= dmi_io_delay_0xed_port,
++		.ident		= "HP Pavilion dv6000",
++		.matches	= {
++			DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"),
++			DMI_MATCH(DMI_BOARD_NAME, "30B8")
++		}
++	},
++	{
++		.callback	= dmi_io_delay_0xed_port,
+ 		.ident		= "HP Pavilion tx1000",
+ 		.matches	= {
+ 			DMI_MATCH(DMI_BOARD_VENDOR, "Quanta"),
+diff --git a/arch/x86/kernel/mfgpt_32.c b/arch/x86/kernel/mfgpt_32.c
+index 027fc06..b402c0f 100644
+--- a/arch/x86/kernel/mfgpt_32.c
++++ b/arch/x86/kernel/mfgpt_32.c
+@@ -30,6 +30,7 @@
+ 
+ #include <linux/kernel.h>
+ #include <linux/interrupt.h>
++#include <linux/module.h>
+ #include <asm/geode.h>
+ 
+ static struct mfgpt_timer_t {
+diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
+index d5904ee..eb92ccb 100644
+--- a/arch/x86/kernel/ptrace.c
++++ b/arch/x86/kernel/ptrace.c
+@@ -600,21 +600,6 @@ static int ptrace_bts_read_record(struct task_struct *child,
+ 	return sizeof(ret);
+ }
+ 
+-static int ptrace_bts_write_record(struct task_struct *child,
+-				   const struct bts_struct *in)
+-{
+-	int retval;
+-
+-	if (!child->thread.ds_area_msr)
+-		return -ENXIO;
+-
+-	retval = ds_write_bts((void *)child->thread.ds_area_msr, in);
+-	if (retval)
+-		return retval;
+-
+-	return sizeof(*in);
+-}
+-
+ static int ptrace_bts_clear(struct task_struct *child)
+ {
+ 	if (!child->thread.ds_area_msr)
+@@ -657,75 +642,6 @@ static int ptrace_bts_drain(struct task_struct *child,
+ 	return end;
+ }
+ 
+-static int ptrace_bts_realloc(struct task_struct *child,
+-			      int size, int reduce_size)
+-{
+-	unsigned long rlim, vm;
+-	int ret, old_size;
+-
+-	if (size < 0)
+-		return -EINVAL;
+-
+-	old_size = ds_get_bts_size((void *)child->thread.ds_area_msr);
+-	if (old_size < 0)
+-		return old_size;
+-
+-	ret = ds_free((void **)&child->thread.ds_area_msr);
+-	if (ret < 0)
+-		goto out;
+-
+-	size >>= PAGE_SHIFT;
+-	old_size >>= PAGE_SHIFT;
+-
+-	current->mm->total_vm  -= old_size;
+-	current->mm->locked_vm -= old_size;
+-
+-	if (size == 0)
+-		goto out;
+-
+-	rlim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT;
+-	vm = current->mm->total_vm  + size;
+-	if (rlim < vm) {
+-		ret = -ENOMEM;
+-
+-		if (!reduce_size)
+-			goto out;
+-
+-		size = rlim - current->mm->total_vm;
+-		if (size <= 0)
+-			goto out;
+-	}
+-
+-	rlim = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT;
+-	vm = current->mm->locked_vm  + size;
+-	if (rlim < vm) {
+-		ret = -ENOMEM;
+-
+-		if (!reduce_size)
+-			goto out;
+-
+-		size = rlim - current->mm->locked_vm;
+-		if (size <= 0)
+-			goto out;
+-	}
+-
+-	ret = ds_allocate((void **)&child->thread.ds_area_msr,
+-			  size << PAGE_SHIFT);
+-	if (ret < 0)
+-		goto out;
+-
+-	current->mm->total_vm  += size;
+-	current->mm->locked_vm += size;
+-
+-out:
+-	if (child->thread.ds_area_msr)
+-		set_tsk_thread_flag(child, TIF_DS_AREA_MSR);
+-	else
+-		clear_tsk_thread_flag(child, TIF_DS_AREA_MSR);
+-
+-	return ret;
+-}
+-
+ static int ptrace_bts_config(struct task_struct *child,
+ 			     long cfg_size,
+ 			     const struct ptrace_bts_config __user *ucfg)
+@@ -828,6 +744,91 @@ static int ptrace_bts_status(struct task_struct *child,
+ 	return sizeof(cfg);
+ }
+ 
++
++static int ptrace_bts_write_record(struct task_struct *child,
++				   const struct bts_struct *in)
++{
++	int retval;
++
++	if (!child->thread.ds_area_msr)
++		return -ENXIO;
++
++	retval = ds_write_bts((void *)child->thread.ds_area_msr, in);
++	if (retval)
++		return retval;
++
++	return sizeof(*in);
++}
++
++static int ptrace_bts_realloc(struct task_struct *child,
++			      int size, int reduce_size)
++{
++	unsigned long rlim, vm;
++	int ret, old_size;
++
++	if (size < 0)
++		return -EINVAL;
++
++	old_size = ds_get_bts_size((void *)child->thread.ds_area_msr);
++	if (old_size < 0)
++		return old_size;
++
++	ret = ds_free((void **)&child->thread.ds_area_msr);
++	if (ret < 0)
++		goto out;
++
++	size >>= PAGE_SHIFT;
++	old_size >>= PAGE_SHIFT;
++
++	current->mm->total_vm  -= old_size;
++	current->mm->locked_vm -= old_size;
++
++	if (size == 0)
++		goto out;
++
++	rlim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT;
++	vm = current->mm->total_vm  + size;
++	if (rlim < vm) {
++		ret = -ENOMEM;
++
++		if (!reduce_size)
++			goto out;
++
++		size = rlim - current->mm->total_vm;
++		if (size <= 0)
++			goto out;
++	}
++
++	rlim = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT;
++	vm = current->mm->locked_vm  + size;
++	if (rlim < vm) {
++		ret = -ENOMEM;
++
++		if (!reduce_size)
++			goto out;
++
++		size = rlim - current->mm->locked_vm;
++		if (size <= 0)
++			goto out;
++	}
++
++	ret = ds_allocate((void **)&child->thread.ds_area_msr,
++			  size << PAGE_SHIFT);
++	if (ret < 0)
++		goto out;
++
++	current->mm->total_vm  += size;
++	current->mm->locked_vm += size;
++
++out:
++	if (child->thread.ds_area_msr)
++		set_tsk_thread_flag(child, TIF_DS_AREA_MSR);
++	else
++		clear_tsk_thread_flag(child, TIF_DS_AREA_MSR);
++
++	return ret;
++}
++
+ void ptrace_bts_take_timestamp(struct task_struct *tsk,
+ 			       enum bts_qualifier qualifier)
+ {
+diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c
+index a1d7071..2b3e5d4 100644
+--- a/arch/x86/kernel/setup_32.c
++++ b/arch/x86/kernel/setup_32.c
+@@ -406,8 +406,6 @@ static unsigned long __init setup_memory(void)
+ 	 */
+ 	min_low_pfn = PFN_UP(init_pg_tables_end);
+ 
+-	find_max_pfn();
+-
+ 	max_low_pfn = find_max_low_pfn();
+ 
+ #ifdef CONFIG_HIGHMEM
+@@ -764,12 +762,13 @@ void __init setup_arch(char **cmdline_p)
+ 	if (efi_enabled)
+ 		efi_init();
+ 
+-	max_low_pfn = setup_memory();
+-
+ 	/* update e820 for memory not covered by WB MTRRs */
++	find_max_pfn();
+ 	mtrr_bp_init();
+ 	if (mtrr_trim_uncached_memory(max_pfn))
+-		max_low_pfn = setup_memory();
++		find_max_pfn();
++
++	max_low_pfn = setup_memory();
+ 
+ #ifdef CONFIG_VMI
+ 	/*
+diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c
+index 7637dc9..f4f7ecf 100644
+--- a/arch/x86/kernel/setup_64.c
++++ b/arch/x86/kernel/setup_64.c
+@@ -801,7 +801,7 @@ static void __cpuinit 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);
+ 
+diff --git a/arch/x86/mach-rdc321x/gpio.c b/arch/x86/mach-rdc321x/gpio.c
+index 0312691..247f33d 100644
+--- a/arch/x86/mach-rdc321x/gpio.c
++++ b/arch/x86/mach-rdc321x/gpio.c
+@@ -1,91 +1,194 @@
+ /*
+- *  Copyright (C) 2007, OpenWrt.org, Florian Fainelli <florian at openwrt.org>
+- *  	RDC321x architecture specific GPIO support
++ *  GPIO support for RDC SoC R3210/R8610
++ *
++ *  Copyright (C) 2007, Florian Fainelli <florian at openwrt.org>
++ *  Copyright (C) 2008, Volker Weiss <dev at tintuc.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., 675 Mass Ave, Cambridge, MA 02139, USA.
+  *
+- *  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/autoconf.h>
+-#include <linux/init.h>
++
++#include <linux/spinlock.h>
+ #include <linux/io.h>
+ #include <linux/types.h>
+ #include <linux/module.h>
+-#include <linux/delay.h>
+ 
++#include <asm/gpio.h>
+ #include <asm/mach-rdc321x/rdc321x_defs.h>
+ 
+-static inline int rdc_gpio_is_valid(unsigned gpio)
++
++/* spin lock to protect our private copy of GPIO data register plus
++   the access to PCI conf registers. */
++static DEFINE_SPINLOCK(gpio_lock);
++
++/* copy of GPIO data registers */
++static u32 gpio_data_reg1;
++static u32 gpio_data_reg2;
++
++static u32 gpio_request_data[2];
++
++
++static inline void rdc321x_conf_write(unsigned addr, u32 value)
+ {
+-	return (gpio <= RDC_MAX_GPIO);
++	outl((1 << 31) | (7 << 11) | addr, RDC3210_CFGREG_ADDR);
++	outl(value, RDC3210_CFGREG_DATA);
+ }
+ 
+-static unsigned int rdc_gpio_read(unsigned gpio)
++static inline void rdc321x_conf_or(unsigned addr, u32 value)
+ {
+-	unsigned int val;
+-
+-	val = 0x80000000 | (7 << 11) | ((gpio&0x20?0x84:0x48));
+-	outl(val, RDC3210_CFGREG_ADDR);
+-	udelay(10);
+-	val = inl(RDC3210_CFGREG_DATA);
+-	val |= (0x1 << (gpio & 0x1F));
+-	outl(val, RDC3210_CFGREG_DATA);
+-	udelay(10);
+-	val = 0x80000000 | (7 << 11) | ((gpio&0x20?0x88:0x4C));
+-	outl(val, RDC3210_CFGREG_ADDR);
+-	udelay(10);
+-	val = inl(RDC3210_CFGREG_DATA);
+-
+-	return val;
++	outl((1 << 31) | (7 << 11) | addr, RDC3210_CFGREG_ADDR);
++	value |= inl(RDC3210_CFGREG_DATA);
++	outl(value, RDC3210_CFGREG_DATA);
+ }
+ 
+-static void rdc_gpio_write(unsigned int val)
++static inline u32 rdc321x_conf_read(unsigned addr)
+ {
+-	if (val) {
+-		outl(val, RDC3210_CFGREG_DATA);
+-		udelay(10);
+-	}
++	outl((1 << 31) | (7 << 11) | addr, RDC3210_CFGREG_ADDR);
++
++	return inl(RDC3210_CFGREG_DATA);
+ }
+ 
+-int rdc_gpio_get_value(unsigned gpio)
++/* configure pin as GPIO */
++static void rdc321x_configure_gpio(unsigned gpio)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&gpio_lock, flags);
++	rdc321x_conf_or(gpio < 32
++		? RDC321X_GPIO_CTRL_REG1 : RDC321X_GPIO_CTRL_REG2,
++		1 << (gpio & 0x1f));
++	spin_unlock_irqrestore(&gpio_lock, flags);
++}
++
++/* initially setup the 2 copies of the gpio data registers.
++   This function must be called by the platform setup code. */
++void __init rdc321x_gpio_setup()
++{
++	/* this might not be, what others (BIOS, bootloader, etc.)
++	   wrote to these registers before, but it's a good guess. Still
++	   better than just using 0xffffffff. */
++
++	gpio_data_reg1 = rdc321x_conf_read(RDC321X_GPIO_DATA_REG1);
++	gpio_data_reg2 = rdc321x_conf_read(RDC321X_GPIO_DATA_REG2);
++}
++
++/* determine, if gpio number is valid */
++static inline int rdc321x_is_gpio(unsigned gpio)
++{
++	return gpio <= RDC321X_MAX_GPIO;
++}
++
++/* request GPIO */
++int rdc_gpio_request(unsigned gpio, const char *label)
+ {
+-	if (rdc_gpio_is_valid(gpio))
+-		return (int)rdc_gpio_read(gpio);
+-	else
++	unsigned long flags;
++
++	if (!rdc321x_is_gpio(gpio))
+ 		return -EINVAL;
++
++	spin_lock_irqsave(&gpio_lock, flags);
++	if (gpio_request_data[(gpio & 0x20) ? 1 : 0] & (1 << (gpio & 0x1f)))
++		goto inuse;
++	gpio_request_data[(gpio & 0x20) ? 1 : 0] |= (1 << (gpio & 0x1f));
++	spin_unlock_irqrestore(&gpio_lock, flags);
++
++	return 0;
++inuse:
++	spin_unlock_irqrestore(&gpio_lock, flags);
++	return -EINVAL;
+ }
+-EXPORT_SYMBOL(rdc_gpio_get_value);
++EXPORT_SYMBOL(rdc_gpio_request);
+ 
+-void rdc_gpio_set_value(unsigned gpio, int value)
++/* release previously-claimed GPIO */
++void rdc_gpio_free(unsigned gpio)
+ {
+-	unsigned int val;
++	unsigned long flags;
+ 
+-	if (!rdc_gpio_is_valid(gpio))
++	if (!rdc321x_is_gpio(gpio))
+ 		return;
+ 
+-	val = rdc_gpio_read(gpio);
++	spin_lock_irqsave(&gpio_lock, flags);
++	gpio_request_data[(gpio & 0x20) ? 1 : 0] &= ~(1 << (gpio & 0x1f));
++	spin_unlock_irqrestore(&gpio_lock, flags);
++}
++EXPORT_SYMBOL(rdc_gpio_free);
++
++/* read GPIO pin */
++int rdc_gpio_get_value(unsigned gpio)
++{
++	u32 reg;
++	unsigned long flags;
++
++	spin_lock_irqsave(&gpio_lock, flags);
++	reg = rdc321x_conf_read(gpio < 32
++		? RDC321X_GPIO_DATA_REG1 : RDC321X_GPIO_DATA_REG2);
++	spin_unlock_irqrestore(&gpio_lock, flags);
+ 
+-	if (value)
+-		val &= ~(0x1 << (gpio & 0x1F));
+-	else
+-		val |= (0x1 << (gpio & 0x1F));
++	return (1 << (gpio & 0x1f)) & reg ? 1 : 0;
++}
++EXPORT_SYMBOL(rdc_gpio_get_value);
+ 
+-	rdc_gpio_write(val);
++/* set GPIO pin to value */
++void rdc_gpio_set_value(unsigned gpio, int value)
++{
++	unsigned long flags;
++	u32 reg;
++
++	reg = 1 << (gpio & 0x1f);
++	if (gpio < 32) {
++		spin_lock_irqsave(&gpio_lock, flags);
++		if (value)
++			gpio_data_reg1 |= reg;
++		else
++			gpio_data_reg1 &= ~reg;
++		rdc321x_conf_write(RDC321X_GPIO_DATA_REG1, gpio_data_reg1);
++		spin_unlock_irqrestore(&gpio_lock, flags);
++	} else {
++		spin_lock_irqsave(&gpio_lock, flags);
++		if (value)
++			gpio_data_reg2 |= reg;
++		else
++			gpio_data_reg2 &= ~reg;
++		rdc321x_conf_write(RDC321X_GPIO_DATA_REG2, gpio_data_reg2);
++		spin_unlock_irqrestore(&gpio_lock, flags);
++	}
+ }
+ EXPORT_SYMBOL(rdc_gpio_set_value);
+ 
++/* configure GPIO pin as input */
+ int rdc_gpio_direction_input(unsigned gpio)
+ {
++	if (!rdc321x_is_gpio(gpio))
++		return -EINVAL;
++
++	rdc321x_configure_gpio(gpio);
++
+ 	return 0;
+ }
+ EXPORT_SYMBOL(rdc_gpio_direction_input);
+ 
++/* configure GPIO pin as output and set value */
+ int rdc_gpio_direction_output(unsigned gpio, int value)
+ {
++	if (!rdc321x_is_gpio(gpio))
++		return -EINVAL;
++
++	gpio_set_value(gpio, value);
++	rdc321x_configure_gpio(gpio);
++
+ 	return 0;
+ }
+ EXPORT_SYMBOL(rdc_gpio_direction_output);
+-
+-
+diff --git a/arch/x86/mach-rdc321x/platform.c b/arch/x86/mach-rdc321x/platform.c
+index dda6024..a037041 100644
+--- a/arch/x86/mach-rdc321x/platform.c
++++ b/arch/x86/mach-rdc321x/platform.c
+@@ -62,6 +62,8 @@ static struct platform_device *rdc321x_devs[] = {
+ 
+ static int __init rdc_board_setup(void)
+ {
++	rdc321x_gpio_setup();
++
+ 	return platform_add_devices(rdc321x_devs, ARRAY_SIZE(rdc321x_devs));
+ }
+ 
+diff --git a/arch/x86/mm/discontig_32.c b/arch/x86/mm/discontig_32.c
+index c394ca0..8e25e06 100644
+--- a/arch/x86/mm/discontig_32.c
++++ b/arch/x86/mm/discontig_32.c
+@@ -324,7 +324,6 @@ unsigned long __init setup_memory(void)
+ 	 * this space and use it to adjust the boundary between ZONE_NORMAL
+ 	 * and ZONE_HIGHMEM.
+ 	 */
+-	find_max_pfn();
+ 	get_memcfg_numa();
+ 
+ 	kva_pages = calculate_numa_remap_pages();
+diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
+index fdc6674..ec08d83 100644
+--- a/arch/x86/mm/fault.c
++++ b/arch/x86/mm/fault.c
+@@ -91,12 +91,10 @@ static int is_prefetch(struct pt_regs *regs, unsigned long addr,
+ 	int prefetch = 0;
+ 	unsigned char *max_instr;
+ 
+-#ifdef CONFIG_X86_32
+-	if (!(__supported_pte_mask & _PAGE_NX))
+-		return 0;
+-#endif
+-
+-	/* If it was a exec fault on NX page, ignore */
++	/*
++	 * If it was a exec (instruction fetch) fault on NX page, then
++	 * do not ignore the fault:
++	 */
+ 	if (error_code & PF_INSTR)
+ 		return 0;
+ 
+diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c
+index 4fbafb4..0b3d567 100644
+--- a/arch/x86/mm/hugetlbpage.c
++++ b/arch/x86/mm/hugetlbpage.c
+@@ -178,7 +178,7 @@ follow_huge_addr(struct mm_struct *mm, unsigned long address, int write)
+ 
+ 	page = &pte_page(*pte)[vpfn % (HPAGE_SIZE/PAGE_SIZE)];
+ 
+-	WARN_ON(!PageCompound(page));
++	WARN_ON(!PageHead(page));
+ 
+ 	return page;
+ }
+diff --git a/arch/x86/mm/ioremap.c b/arch/x86/mm/ioremap.c
+index 4afaba0..794895c 100644
+--- a/arch/x86/mm/ioremap.c
++++ b/arch/x86/mm/ioremap.c
+@@ -137,7 +137,11 @@ static void __iomem *__ioremap(resource_size_t phys_addr, unsigned long size,
+ 	switch (mode) {
+ 	case IOR_MODE_UNCACHED:
+ 	default:
+-		prot = PAGE_KERNEL_NOCACHE;
++		/*
++		 * 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;
+diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
+index 14e48b5..7b79f6b 100644
+--- a/arch/x86/mm/pageattr.c
++++ b/arch/x86/mm/pageattr.c
+@@ -771,7 +771,7 @@ static inline int change_page_attr_clear(unsigned long addr, int numpages,
+ int set_memory_uc(unsigned long addr, int numpages)
+ {
+ 	return change_page_attr_set(addr, numpages,
+-				    __pgprot(_PAGE_PCD | _PAGE_PWT));
++				    __pgprot(_PAGE_PCD));
+ }
+ EXPORT_SYMBOL(set_memory_uc);
+ 
+diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
+index 8b9ee27..de4e6f0 100644
+--- a/arch/x86/xen/enlighten.c
++++ b/arch/x86/xen/enlighten.c
+@@ -95,7 +95,7 @@ struct shared_info *HYPERVISOR_shared_info = (void *)&dummy_shared_info;
+  *
+  * 0: not available, 1: available
+  */
+-static int have_vcpu_info_placement = 0;
++static int have_vcpu_info_placement = 1;
+ 
+ static void __init xen_vcpu_setup(int cpu)
+ {
+@@ -103,6 +103,7 @@ static void __init xen_vcpu_setup(int cpu)
+ 	int err;
+ 	struct vcpu_info *vcpup;
+ 
++	BUG_ON(HYPERVISOR_shared_info == &dummy_shared_info);
+ 	per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
+ 
+ 	if (!have_vcpu_info_placement)
+@@ -805,33 +806,43 @@ static __init void xen_pagetable_setup_start(pgd_t *base)
+ 			  PFN_DOWN(__pa(xen_start_info->pt_base)));
+ }
+ 
+-static __init void xen_pagetable_setup_done(pgd_t *base)
++static __init void setup_shared_info(void)
+ {
+-	/* This will work as long as patching hasn't happened yet
+-	   (which it hasn't) */
+-	pv_mmu_ops.alloc_pt = xen_alloc_pt;
+-	pv_mmu_ops.alloc_pd = xen_alloc_pd;
+-	pv_mmu_ops.release_pt = xen_release_pt;
+-	pv_mmu_ops.release_pd = xen_release_pt;
+-	pv_mmu_ops.set_pte = xen_set_pte;
+-
+ 	if (!xen_feature(XENFEAT_auto_translated_physmap)) {
++		unsigned long addr = fix_to_virt(FIX_PARAVIRT_BOOTMAP);
++
+ 		/*
+ 		 * Create a mapping for the shared info page.
+ 		 * Should be set_fixmap(), but shared_info is a machine
+ 		 * address with no corresponding pseudo-phys address.
+ 		 */
+-		set_pte_mfn(fix_to_virt(FIX_PARAVIRT_BOOTMAP),
++		set_pte_mfn(addr,
+ 			    PFN_DOWN(xen_start_info->shared_info),
+ 			    PAGE_KERNEL);
+ 
+-		HYPERVISOR_shared_info =
+-			(struct shared_info *)fix_to_virt(FIX_PARAVIRT_BOOTMAP);
+-
++		HYPERVISOR_shared_info = (struct shared_info *)addr;
+ 	} else
+ 		HYPERVISOR_shared_info =
+ 			(struct shared_info *)__va(xen_start_info->shared_info);
+ 
++#ifndef CONFIG_SMP
++	/* In UP this is as good a place as any to set up shared info */
++	xen_setup_vcpu_info_placement();
++#endif
++}
++
++static __init void xen_pagetable_setup_done(pgd_t *base)
++{
++	/* This will work as long as patching hasn't happened yet
++	   (which it hasn't) */
++	pv_mmu_ops.alloc_pt = xen_alloc_pt;
++	pv_mmu_ops.alloc_pd = xen_alloc_pd;
++	pv_mmu_ops.release_pt = xen_release_pt;
++	pv_mmu_ops.release_pd = xen_release_pt;
++	pv_mmu_ops.set_pte = xen_set_pte;
++
++	setup_shared_info();
++
+ 	/* Actually pin the pagetable down, but we can't set PG_pinned
+ 	   yet because the page structures don't exist yet. */
+ 	{
+@@ -1182,15 +1193,9 @@ asmlinkage void __init xen_start_kernel(void)
+ 	x86_write_percpu(xen_cr3, __pa(pgd));
+ 	x86_write_percpu(xen_current_cr3, __pa(pgd));
+ 
+-#ifdef CONFIG_SMP
+ 	/* Don't do the full vcpu_info placement stuff until we have a
+-	   possible map. */
++	   possible map and a non-dummy shared_info. */
+ 	per_cpu(xen_vcpu, 0) = &HYPERVISOR_shared_info->vcpu_info[0];
+-#else
+-	/* May as well do it now, since there's no good time to call
+-	   it later on UP. */
+-	xen_setup_vcpu_info_placement();
+-#endif
+ 
+ 	pv_info.kernel_rpl = 1;
+ 	if (xen_feature(XENFEAT_supervisor_mode_kernel))
+diff --git a/arch/x86/xen/xen-asm.S b/arch/x86/xen/xen-asm.S
+index 1a43b60..6b71904 100644
+--- a/arch/x86/xen/xen-asm.S
++++ b/arch/x86/xen/xen-asm.S
+@@ -33,12 +33,17 @@
+ 	events, then enter the hypervisor to get them handled.
+  */
+ ENTRY(xen_irq_enable_direct)
+-	/* Clear mask and test pending */
+-	andw $0x00ff, PER_CPU_VAR(xen_vcpu_info)+XEN_vcpu_info_pending
++	/* Unmask events */
++	movb $0, PER_CPU_VAR(xen_vcpu_info)+XEN_vcpu_info_mask
++
+ 	/* Preempt here doesn't matter because that will deal with
+ 	   any pending interrupts.  The pending check may end up being
+ 	   run on the wrong CPU, but that doesn't hurt. */
++
++	/* Test for pending */
++	testb $0xff, PER_CPU_VAR(xen_vcpu_info)+XEN_vcpu_info_pending
+ 	jz 1f
++
+ 2:	call check_events
+ 1:
+ ENDPATCH(xen_irq_enable_direct)
+diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
+index c8e3cba..4d535c5 100644
+--- a/drivers/acpi/fan.c
++++ b/drivers/acpi/fan.c
+@@ -260,24 +260,22 @@ static int acpi_fan_add(struct acpi_device *device)
+ 		result = PTR_ERR(cdev);
+ 		goto end;
+ 	}
+-	if (cdev) {
+-		printk(KERN_INFO PREFIX
+-			"%s is registered as cooling_device%d\n",
+-			device->dev.bus_id, cdev->id);
+-
+-		acpi_driver_data(device) = cdev;
+-		result = sysfs_create_link(&device->dev.kobj,
+-					   &cdev->device.kobj,
+-					   "thermal_cooling");
+-		if (result)
+-			return result;
+-
+-		result = sysfs_create_link(&cdev->device.kobj,
+-					   &device->dev.kobj,
+-					   "device");
+-		if (result)
+-			return result;
+-	}
++	printk(KERN_INFO PREFIX
++		"%s is registered as cooling_device%d\n",
++		device->dev.bus_id, cdev->id);
++
++	acpi_driver_data(device) = cdev;
++	result = sysfs_create_link(&device->dev.kobj,
++				   &cdev->device.kobj,
++				   "thermal_cooling");
++	if (result)
++		return result;
++
++	result = sysfs_create_link(&cdev->device.kobj,
++				   &device->dev.kobj,
++				   "device");
++	if (result)
++		return result;
+ 
+ 	result = acpi_fan_add_fs(device);
+ 	if (result)
+diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
+index 36a68fa..3a136f6 100644
+--- a/drivers/acpi/processor_core.c
++++ b/drivers/acpi/processor_core.c
+@@ -674,22 +674,20 @@ static int __cpuinit acpi_processor_start(struct acpi_device *device)
+ 		result = PTR_ERR(pr->cdev);
+ 		goto end;
+ 	}
+-	if (pr->cdev) {
+-		printk(KERN_INFO PREFIX
+-			"%s is registered as cooling_device%d\n",
+-			device->dev.bus_id, pr->cdev->id);
+-
+-		result = sysfs_create_link(&device->dev.kobj,
+-					   &pr->cdev->device.kobj,
+-					   "thermal_cooling");
+-		if (result)
+-			return result;
+-		result = sysfs_create_link(&pr->cdev->device.kobj,
+-					   &device->dev.kobj,
+-					   "device");
+-		if (result)
+-			return result;
+-	}
++	printk(KERN_INFO PREFIX
++		"%s is registered as cooling_device%d\n",
++		device->dev.bus_id, pr->cdev->id);
++
++	result = sysfs_create_link(&device->dev.kobj,
++				   &pr->cdev->device.kobj,
++				   "thermal_cooling");
++	if (result)
++		return result;
++	result = sysfs_create_link(&pr->cdev->device.kobj,
++				   &device->dev.kobj,
++				   "device");
++	if (result)
++		return result;
+ 
+ 	if (pr->flags.throttling) {
+ 		printk(KERN_INFO PREFIX "%s [%s] (supports",
+diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
+index e8e2d88..788da97 100644
+--- a/drivers/acpi/processor_idle.c
++++ b/drivers/acpi/processor_idle.c
+@@ -1487,7 +1487,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
+ 		return 0;
+ 	}
+ 
+-	acpi_unlazy_tlb(smp_processor_id());
+ 	/*
+ 	 * Must be done before busmaster disable as we might need to
+ 	 * access HPET !
+@@ -1577,6 +1576,8 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
+ 		return 0;
+ 	}
+ 
++	acpi_unlazy_tlb(smp_processor_id());
++
+ 	/* Tell the scheduler that we are going deep-idle: */
+ 	sched_clock_idle_sleep_event();
+ 	/*
+@@ -1692,7 +1693,9 @@ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr)
+ 		switch (cx->type) {
+ 			case ACPI_STATE_C1:
+ 			state->flags |= CPUIDLE_FLAG_SHALLOW;
+-			state->flags |= CPUIDLE_FLAG_TIME_VALID;
++			if (cx->entry_method == ACPI_CSTATE_FFH)
++				state->flags |= CPUIDLE_FLAG_TIME_VALID;
++
+ 			state->enter = acpi_idle_enter_c1;
+ 			dev->safe_state = state;
+ 			break;
+diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c
+index a2cf300..bcf2c70 100644
+--- a/drivers/acpi/sbshc.c
++++ b/drivers/acpi/sbshc.c
+@@ -130,7 +130,6 @@ static int acpi_smbus_transaction(struct acpi_smb_hc *hc, u8 protocol,
+ 		goto end;
+ 	}
+ 	smb_hc_write(hc, ACPI_SMB_COMMAND, command);
+-	smb_hc_write(hc, ACPI_SMB_COMMAND, command);
+ 	if (!(protocol & 0x01)) {
+ 		smb_hc_write(hc, ACPI_SMB_BLOCK_COUNT, length);
+ 		for (i = 0; i < length; ++i)
+diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
+index 57570ac..e6ce262 100644
+--- a/drivers/acpi/scan.c
++++ b/drivers/acpi/scan.c
+@@ -39,20 +39,26 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
+ 			   int size)
+ {
+ 	int len;
++	int count;
+ 
+-	if (!acpi_dev->flags.hardware_id)
++	if (!acpi_dev->flags.hardware_id && !acpi_dev->flags.compatible_ids)
+ 		return -ENODEV;
+ 
+-	len = snprintf(modalias, size, "acpi:%s:",
+-		       acpi_dev->pnp.hardware_id);
+-	if (len < 0 || len >= size)
+-		return -EINVAL;
++	len = snprintf(modalias, size, "acpi:");
+ 	size -= len;
+ 
++	if (acpi_dev->flags.hardware_id) {
++		count = snprintf(&modalias[len], size, "%s:",
++				 acpi_dev->pnp.hardware_id);
++		if (count < 0 || count >= size)
++			return -EINVAL;
++		len += count;
++		size -= count;
++	}
++
+ 	if (acpi_dev->flags.compatible_ids) {
+ 		struct acpi_compatible_id_list *cid_list;
+ 		int i;
+-		int count;
+ 
+ 		cid_list = acpi_dev->pnp.cid_list;
+ 		for (i = 0; i < cid_list->count; i++) {
+diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c
+index 12fb44f..fe09b57 100644
+--- a/drivers/acpi/video.c
++++ b/drivers/acpi/video.c
+@@ -734,21 +734,19 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device)
+ 		if (IS_ERR(device->cdev))
+ 			return;
+ 
+-		if (device->cdev) {
+-			printk(KERN_INFO PREFIX
+-				"%s is registered as cooling_device%d\n",
+-				device->dev->dev.bus_id, device->cdev->id);
+-			result = sysfs_create_link(&device->dev->dev.kobj,
+-					  &device->cdev->device.kobj,
+-					  "thermal_cooling");
+-			if (result)
+-				printk(KERN_ERR PREFIX "Create sysfs link\n");
+-			result = sysfs_create_link(&device->cdev->device.kobj,
+-					  &device->dev->dev.kobj,
+-					  "device");
+-                        if (result)
+-				printk(KERN_ERR PREFIX "Create sysfs link\n");
+-		}
++		printk(KERN_INFO PREFIX
++			"%s is registered as cooling_device%d\n",
++			device->dev->dev.bus_id, device->cdev->id);
++		result = sysfs_create_link(&device->dev->dev.kobj,
++				  &device->cdev->device.kobj,
++				  "thermal_cooling");
++		if (result)
++			printk(KERN_ERR PREFIX "Create sysfs link\n");
++		result = sysfs_create_link(&device->cdev->device.kobj,
++				  &device->dev->dev.kobj,
++				  "device");
++		if (result)
++			printk(KERN_ERR PREFIX "Create sysfs link\n");
+ 	}
+ 	if (device->cap._DCS && device->cap._DSS){
+ 		static int count = 0;
+diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
+index d73663a..fc555a9 100644
+--- a/drivers/cpuidle/cpuidle.c
++++ b/drivers/cpuidle/cpuidle.c
+@@ -67,7 +67,7 @@ static void cpuidle_idle_call(void)
+ 	/* enter the state and update stats */
+ 	dev->last_residency = target_state->enter(dev, target_state);
+ 	dev->last_state = target_state;
+-	target_state->time += dev->last_residency;
++	target_state->time += (unsigned long long)dev->last_residency;
+ 	target_state->usage++;
+ 
+ 	/* give the governor an opportunity to reflect on the outcome */
+@@ -224,7 +224,7 @@ static void poll_idle_init(struct cpuidle_device *dev)
+ 	state->exit_latency = 0;
+ 	state->target_residency = 0;
+ 	state->power_usage = -1;
+-	state->flags = CPUIDLE_FLAG_POLL | CPUIDLE_FLAG_TIME_VALID;
++	state->flags = CPUIDLE_FLAG_POLL;
+ 	state->enter = poll_idle;
+ }
+ #else
+diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
+index 69102ca..e949618 100644
+--- a/drivers/cpuidle/sysfs.c
++++ b/drivers/cpuidle/sysfs.c
+@@ -218,6 +218,12 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \
+ 	return sprintf(buf, "%u\n", state->_name);\
+ }
+ 
++#define define_show_state_ull_function(_name) \
++static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \
++{ \
++	return sprintf(buf, "%llu\n", state->_name);\
++}
++
+ #define define_show_state_str_function(_name) \
+ static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \
+ { \
+@@ -228,8 +234,8 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, char *buf) \
+ 
+ define_show_state_function(exit_latency)
+ define_show_state_function(power_usage)
+-define_show_state_function(usage)
+-define_show_state_function(time)
++define_show_state_ull_function(usage)
++define_show_state_ull_function(time)
+ define_show_state_str_function(name)
+ define_show_state_str_function(desc)
+ 
+diff --git a/drivers/net/b44.c b/drivers/net/b44.c
+index ea2a2b5..25f1337 100644
+--- a/drivers/net/b44.c
++++ b/drivers/net/b44.c
+@@ -2082,6 +2082,11 @@ static int __devinit b44_get_invariants(struct b44 *bp)
+ 		addr = sdev->bus->sprom.et0mac;
+ 		bp->phy_addr = sdev->bus->sprom.et0phyaddr;
+ 	}
++	/* Some ROMs have buggy PHY addresses with the high
++	 * bits set (sign extension?). Truncate them to a
++	 * valid PHY address. */
++	bp->phy_addr &= 0x1F;
++
+ 	memcpy(bp->dev->dev_addr, addr, 6);
+ 
+ 	if (!is_valid_ether_addr(&bp->dev->dev_addr[0])){
+diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c
+index cb3c6fa..d16e0e1 100644
+--- a/drivers/net/bonding/bond_3ad.c
++++ b/drivers/net/bonding/bond_3ad.c
+@@ -310,7 +310,7 @@ static inline int __check_agg_selection_timer(struct port *port)
+  */
+ static inline void __get_rx_machine_lock(struct port *port)
+ {
+-	spin_lock(&(SLAVE_AD_INFO(port->slave).rx_machine_lock));
++	spin_lock_bh(&(SLAVE_AD_INFO(port->slave).rx_machine_lock));
+ }
+ 
+ /**
+@@ -320,7 +320,7 @@ static inline void __get_rx_machine_lock(struct port *port)
+  */
+ static inline void __release_rx_machine_lock(struct port *port)
+ {
+-	spin_unlock(&(SLAVE_AD_INFO(port->slave).rx_machine_lock));
++	spin_unlock_bh(&(SLAVE_AD_INFO(port->slave).rx_machine_lock));
+ }
+ 
+ /**
+diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c
+index b57bc94..3f58c3d 100644
+--- a/drivers/net/bonding/bond_alb.c
++++ b/drivers/net/bonding/bond_alb.c
+@@ -678,12 +678,8 @@ static struct slave *rlb_choose_channel(struct sk_buff *skb, struct bonding *bon
+ 		}
+ 
+ 		if (!list_empty(&bond->vlan_list)) {
+-			unsigned short vlan_id;
+-			int res = vlan_get_tag(skb, &vlan_id);
+-			if (!res) {
++			if (!vlan_get_tag(skb, &client_info->vlan_id))
+ 				client_info->tag = 1;
+-				client_info->vlan_id = vlan_id;
+-			}
+ 		}
+ 
+ 		if (!client_info->assigned) {
+diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
+index 0942d82..0f06753 100644
+--- a/drivers/net/bonding/bond_main.c
++++ b/drivers/net/bonding/bond_main.c
+@@ -383,7 +383,7 @@ struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr)
+  */
+ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, struct net_device *slave_dev)
+ {
+-	unsigned short vlan_id;
++	unsigned short uninitialized_var(vlan_id);
+ 
+ 	if (!list_empty(&bond->vlan_list) &&
+ 	    !(slave_dev->features & NETIF_F_HW_VLAN_TX) &&
+@@ -4528,8 +4528,7 @@ static void bond_free_all(void)
+ 		netif_tx_unlock_bh(bond_dev);
+ 		/* Release the bonded slaves */
+ 		bond_release_all(bond_dev);
+-		bond_deinit(bond_dev);
+-		unregister_netdevice(bond_dev);
++		bond_destroy(bond);
+ 	}
+ 
+ #ifdef CONFIG_PROC_FS
+diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
+index 67ccad6..a3c74e2 100644
+--- a/drivers/net/bonding/bonding.h
++++ b/drivers/net/bonding/bonding.h
+@@ -22,8 +22,8 @@
+ #include "bond_3ad.h"
+ #include "bond_alb.h"
+ 
+-#define DRV_VERSION	"3.2.4"
+-#define DRV_RELDATE	"January 28, 2008"
++#define DRV_VERSION	"3.2.5"
++#define DRV_RELDATE	"March 21, 2008"
+ #define DRV_NAME	"bonding"
+ #define DRV_DESCRIPTION	"Ethernet Channel Bonding Driver"
+ 
+diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c
+index db58687..98a6bbd 100644
+--- a/drivers/net/cxgb3/sge.c
++++ b/drivers/net/cxgb3/sge.c
+@@ -557,9 +557,9 @@ static void t3_free_qset(struct adapter *adapter, struct sge_qset *q)
+ 
+ 	for (i = 0; i < SGE_RXQ_PER_SET; ++i)
+ 		if (q->fl[i].desc) {
+-			spin_lock(&adapter->sge.reg_lock);
++			spin_lock_irq(&adapter->sge.reg_lock);
+ 			t3_sge_disable_fl(adapter, q->fl[i].cntxt_id);
+-			spin_unlock(&adapter->sge.reg_lock);
++			spin_unlock_irq(&adapter->sge.reg_lock);
+ 			free_rx_bufs(pdev, &q->fl[i]);
+ 			kfree(q->fl[i].sdesc);
+ 			dma_free_coherent(&pdev->dev,
+@@ -570,9 +570,9 @@ static void t3_free_qset(struct adapter *adapter, struct sge_qset *q)
+ 
+ 	for (i = 0; i < SGE_TXQ_PER_SET; ++i)
+ 		if (q->txq[i].desc) {
+-			spin_lock(&adapter->sge.reg_lock);
++			spin_lock_irq(&adapter->sge.reg_lock);
+ 			t3_sge_enable_ecntxt(adapter, q->txq[i].cntxt_id, 0);
+-			spin_unlock(&adapter->sge.reg_lock);
++			spin_unlock_irq(&adapter->sge.reg_lock);
+ 			if (q->txq[i].sdesc) {
+ 				free_tx_desc(adapter, &q->txq[i],
+ 					     q->txq[i].in_use);
+@@ -586,9 +586,9 @@ static void t3_free_qset(struct adapter *adapter, struct sge_qset *q)
+ 		}
+ 
+ 	if (q->rspq.desc) {
+-		spin_lock(&adapter->sge.reg_lock);
++		spin_lock_irq(&adapter->sge.reg_lock);
+ 		t3_sge_disable_rspcntxt(adapter, q->rspq.cntxt_id);
+-		spin_unlock(&adapter->sge.reg_lock);
++		spin_unlock_irq(&adapter->sge.reg_lock);
+ 		dma_free_coherent(&pdev->dev,
+ 				  q->rspq.size * sizeof(struct rsp_desc),
+ 				  q->rspq.desc, q->rspq.phys_addr);
+@@ -2667,7 +2667,7 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
+ 		(16 * 1024) - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) :
+ 		MAX_FRAME_SIZE + 2 + sizeof(struct cpl_rx_pkt);
+ 
+-	spin_lock(&adapter->sge.reg_lock);
++	spin_lock_irq(&adapter->sge.reg_lock);
+ 
+ 	/* FL threshold comparison uses < */
+ 	ret = t3_sge_init_rspcntxt(adapter, q->rspq.cntxt_id, irq_vec_idx,
+@@ -2711,7 +2711,7 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
+ 			goto err_unlock;
+ 	}
+ 
+-	spin_unlock(&adapter->sge.reg_lock);
++	spin_unlock_irq(&adapter->sge.reg_lock);
+ 
+ 	q->adap = adapter;
+ 	q->netdev = dev;
+@@ -2728,7 +2728,7 @@ int t3_sge_alloc_qset(struct adapter *adapter, unsigned int id, int nports,
+ 	return 0;
+ 
+       err_unlock:
+-	spin_unlock(&adapter->sge.reg_lock);
++	spin_unlock_irq(&adapter->sge.reg_lock);
+       err:
+ 	t3_free_qset(adapter, q);
+ 	return ret;
+diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
+index 1fe305c..b09a53d 100644
+--- a/drivers/net/dm9000.c
++++ b/drivers/net/dm9000.c
+@@ -798,8 +798,6 @@ dm9000_init_dm9000(struct net_device *dev)
+ 	/* Set address filter table */
+ 	dm9000_hash_table(dev);
+ 
+-	/* Activate DM9000 */
+-	iow(db, DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
+ 	/* Enable TX/RX interrupt mask */
+ 	iow(db, DM9000_IMR, IMR_PAR | IMR_PTM | IMR_PRM);
+ 
+@@ -1197,6 +1195,7 @@ dm9000_hash_table(struct net_device *dev)
+ 	int i, oft;
+ 	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__);
+@@ -1213,6 +1212,12 @@ dm9000_hash_table(struct net_device *dev)
+ 	/* broadcast address */
+ 	hash_table[3] = 0x8000;
+ 
++	if (dev->flags & IFF_PROMISC)
++		rcr |= RCR_PRMSC;
++
++	if (dev->flags & IFF_ALLMULTI)
++		rcr |= RCR_ALL;
++
+ 	/* the multicast address in Hash Table : 64 bits */
+ 	for (i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
+ 		hash_val = ether_crc_le(6, mcptr->dmi_addr) & 0x3f;
+@@ -1225,6 +1230,7 @@ dm9000_hash_table(struct net_device *dev)
+ 		iow(db, oft++, hash_table[i] >> 8);
+ 	}
+ 
++	iow(db, DM9000_RCR, rcr);
+ 	spin_unlock_irqrestore(&db->lock, flags);
+ }
+ 
+diff --git a/drivers/net/e100.c b/drivers/net/e100.c
+index cdf3090..2d139ec 100644
+--- a/drivers/net/e100.c
++++ b/drivers/net/e100.c
+@@ -960,7 +960,7 @@ static void e100_get_defaults(struct nic *nic)
+ 
+ 	/* Template for a freshly allocated RFD */
+ 	nic->blank_rfd.command = 0;
+-	nic->blank_rfd.rbd = 0xFFFFFFFF;
++	nic->blank_rfd.rbd = cpu_to_le32(0xFFFFFFFF);
+ 	nic->blank_rfd.size = cpu_to_le16(VLAN_ETH_FRAME_LEN);
+ 
+ 	/* MII setup */
+diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h
+index 7c4ead3..93b7fb2 100644
+--- a/drivers/net/ehea/ehea.h
++++ b/drivers/net/ehea/ehea.h
+@@ -40,7 +40,7 @@
+ #include <asm/io.h>
+ 
+ #define DRV_NAME	"ehea"
+-#define DRV_VERSION	"EHEA_0087"
++#define DRV_VERSION	"EHEA_0089"
+ 
+ /* eHEA capability flags */
+ #define DLPAR_PORT_ADD_REM 1
+diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c
+index 21af674..07c742d 100644
+--- a/drivers/net/ehea/ehea_main.c
++++ b/drivers/net/ehea/ehea_main.c
+@@ -3108,7 +3108,7 @@ struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter,
+ 	dev->vlan_rx_add_vid = ehea_vlan_rx_add_vid;
+ 	dev->vlan_rx_kill_vid = ehea_vlan_rx_kill_vid;
+ 	dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO
+-		      | NETIF_F_HIGHDMA | NETIF_F_HW_CSUM | NETIF_F_HW_VLAN_TX
++		      | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX
+ 		      | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER
+ 		      | NETIF_F_LLTX;
+ 	dev->tx_timeout = &ehea_tx_watchdog;
+diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h
+index 6604d96..76ea846 100644
+--- a/drivers/net/igb/e1000_82575.h
++++ b/drivers/net/igb/e1000_82575.h
+@@ -61,28 +61,28 @@
+ /* Receive Descriptor - Advanced */
+ union e1000_adv_rx_desc {
+ 	struct {
+-		u64 pkt_addr;             /* Packet buffer address */
+-		u64 hdr_addr;             /* Header buffer address */
++		__le64 pkt_addr;             /* Packet buffer address */
++		__le64 hdr_addr;             /* Header buffer address */
+ 	} read;
+ 	struct {
+ 		struct {
+ 			struct {
+-				u16 pkt_info;   /* RSS type, Packet type */
+-				u16 hdr_info;   /* Split Header,
+-						 * header buffer length */
++				__le16 pkt_info;   /* RSS type, Packet type */
++				__le16 hdr_info;   /* Split Header,
++						    * header buffer length */
+ 			} lo_dword;
+ 			union {
+-				u32 rss;          /* RSS Hash */
++				__le32 rss;          /* RSS Hash */
+ 				struct {
+-					u16 ip_id;    /* IP id */
+-					u16 csum;     /* Packet Checksum */
++					__le16 ip_id;    /* IP id */
++					__le16 csum;     /* Packet Checksum */
+ 				} csum_ip;
+ 			} hi_dword;
+ 		} lower;
+ 		struct {
+-			u32 status_error;     /* ext status/error */
+-			u16 length;           /* Packet length */
+-			u16 vlan;             /* VLAN tag */
++			__le32 status_error;     /* ext status/error */
++			__le16 length;           /* Packet length */
++			__le16 vlan;             /* VLAN tag */
+ 		} upper;
+ 	} wb;  /* writeback */
+ };
+@@ -97,14 +97,14 @@ union e1000_adv_rx_desc {
+ /* Transmit Descriptor - Advanced */
+ union e1000_adv_tx_desc {
+ 	struct {
+-		u64 buffer_addr;    /* Address of descriptor's data buf */
+-		u32 cmd_type_len;
+-		u32 olinfo_status;
++		__le64 buffer_addr;    /* Address of descriptor's data buf */
++		__le32 cmd_type_len;
++		__le32 olinfo_status;
+ 	} read;
+ 	struct {
+-		u64 rsvd;       /* Reserved */
+-		u32 nxtseq_seed;
+-		u32 status;
++		__le64 rsvd;       /* Reserved */
++		__le32 nxtseq_seed;
++		__le32 status;
+ 	} wb;
+ };
+ 
+@@ -119,10 +119,10 @@ union e1000_adv_tx_desc {
+ 
+ /* Context descriptors */
+ struct e1000_adv_tx_context_desc {
+-	u32 vlan_macip_lens;
+-	u32 seqnum_seed;
+-	u32 type_tucmd_mlhl;
+-	u32 mss_l4len_idx;
++	__le32 vlan_macip_lens;
++	__le32 seqnum_seed;
++	__le32 type_tucmd_mlhl;
++	__le32 mss_l4len_idx;
+ };
+ 
+ #define E1000_ADVTXD_MACLEN_SHIFT    9  /* Adv ctxt desc mac len shift */
+diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h
+index 161fb68..7b2c70a 100644
+--- a/drivers/net/igb/e1000_hw.h
++++ b/drivers/net/igb/e1000_hw.h
+@@ -143,35 +143,35 @@ enum e1000_fc_type {
+ 
+ /* Receive Descriptor */
+ struct e1000_rx_desc {
+-	u64 buffer_addr; /* Address of the descriptor's data buffer */
+-	u16 length;      /* Length of data DMAed into data buffer */
+-	u16 csum;        /* Packet checksum */
++	__le64 buffer_addr; /* Address of the descriptor's data buffer */
++	__le16 length;      /* Length of data DMAed into data buffer */
++	__le16 csum;        /* Packet checksum */
+ 	u8  status;      /* Descriptor status */
+ 	u8  errors;      /* Descriptor Errors */
+-	u16 special;
++	__le16 special;
+ };
+ 
+ /* Receive Descriptor - Extended */
+ union e1000_rx_desc_extended {
+ 	struct {
+-		u64 buffer_addr;
+-		u64 reserved;
++		__le64 buffer_addr;
++		__le64 reserved;
+ 	} read;
+ 	struct {
+ 		struct {
+-			u32 mrq;              /* Multiple Rx Queues */
++			__le32 mrq;              /* Multiple Rx Queues */
+ 			union {
+-				u32 rss;            /* RSS Hash */
++				__le32 rss;            /* RSS Hash */
+ 				struct {
+-					u16 ip_id;  /* IP id */
+-					u16 csum;   /* Packet Checksum */
++					__le16 ip_id;  /* IP id */
++					__le16 csum;   /* Packet Checksum */
+ 				} csum_ip;
+ 			} hi_dword;
+ 		} lower;
+ 		struct {
+-			u32 status_error;     /* ext status/error */
+-			u16 length;
+-			u16 vlan;             /* VLAN tag */
++			__le32 status_error;     /* ext status/error */
++			__le16 length;
++			__le16 vlan;             /* VLAN tag */
+ 		} upper;
+ 	} wb;  /* writeback */
+ };
+@@ -181,49 +181,49 @@ union e1000_rx_desc_extended {
+ union e1000_rx_desc_packet_split {
+ 	struct {
+ 		/* one buffer for protocol header(s), three data buffers */
+-		u64 buffer_addr[MAX_PS_BUFFERS];
++		__le64 buffer_addr[MAX_PS_BUFFERS];
+ 	} read;
+ 	struct {
+ 		struct {
+-			u32 mrq;              /* Multiple Rx Queues */
++			__le32 mrq;              /* Multiple Rx Queues */
+ 			union {
+-				u32 rss;              /* RSS Hash */
++				__le32 rss;              /* RSS Hash */
+ 				struct {
+-					u16 ip_id;    /* IP id */
+-					u16 csum;     /* Packet Checksum */
++					__le16 ip_id;    /* IP id */
++					__le16 csum;     /* Packet Checksum */
+ 				} csum_ip;
+ 			} hi_dword;
+ 		} lower;
+ 		struct {
+-			u32 status_error;     /* ext status/error */
+-			u16 length0;          /* length of buffer 0 */
+-			u16 vlan;             /* VLAN tag */
++			__le32 status_error;     /* ext status/error */
++			__le16 length0;          /* length of buffer 0 */
++			__le16 vlan;             /* VLAN tag */
+ 		} middle;
+ 		struct {
+-			u16 header_status;
+-			u16 length[3];        /* length of buffers 1-3 */
++			__le16 header_status;
++			__le16 length[3];        /* length of buffers 1-3 */
+ 		} upper;
+-		u64 reserved;
++		__le64 reserved;
+ 	} wb; /* writeback */
+ };
+ 
+ /* Transmit Descriptor */
+ struct e1000_tx_desc {
+-	u64 buffer_addr;      /* Address of the descriptor's data buffer */
++	__le64 buffer_addr;      /* Address of the descriptor's data buffer */
+ 	union {
+-		u32 data;
++		__le32 data;
+ 		struct {
+-			u16 length;    /* Data buffer length */
++			__le16 length;    /* Data buffer length */
+ 			u8 cso;        /* Checksum offset */
+ 			u8 cmd;        /* Descriptor control */
+ 		} flags;
+ 	} lower;
+ 	union {
+-		u32 data;
++		__le32 data;
+ 		struct {
+ 			u8 status;     /* Descriptor status */
+ 			u8 css;        /* Checksum start */
+-			u16 special;
++			__le16 special;
+ 		} fields;
+ 	} upper;
+ };
+@@ -231,49 +231,49 @@ struct e1000_tx_desc {
+ /* Offload Context Descriptor */
+ struct e1000_context_desc {
+ 	union {
+-		u32 ip_config;
++		__le32 ip_config;
+ 		struct {
+ 			u8 ipcss;      /* IP checksum start */
+ 			u8 ipcso;      /* IP checksum offset */
+-			u16 ipcse;     /* IP checksum end */
++			__le16 ipcse;     /* IP checksum end */
+ 		} ip_fields;
+ 	} lower_setup;
+ 	union {
+-		u32 tcp_config;
++		__le32 tcp_config;
+ 		struct {
+ 			u8 tucss;      /* TCP checksum start */
+ 			u8 tucso;      /* TCP checksum offset */
+-			u16 tucse;     /* TCP checksum end */
++			__le16 tucse;     /* TCP checksum end */
+ 		} tcp_fields;
+ 	} upper_setup;
+-	u32 cmd_and_length;
++	__le32 cmd_and_length;
+ 	union {
+-		u32 data;
++		__le32 data;
+ 		struct {
+ 			u8 status;     /* Descriptor status */
+ 			u8 hdr_len;    /* Header length */
+-			u16 mss;       /* Maximum segment size */
++			__le16 mss;       /* Maximum segment size */
+ 		} fields;
+ 	} tcp_seg_setup;
+ };
+ 
+ /* Offload data descriptor */
+ struct e1000_data_desc {
+-	u64 buffer_addr;   /* Address of the descriptor's buffer address */
++	__le64 buffer_addr;   /* Address of the descriptor's buffer address */
+ 	union {
+-		u32 data;
++		__le32 data;
+ 		struct {
+-			u16 length;    /* Data buffer length */
++			__le16 length;    /* Data buffer length */
+ 			u8 typ_len_ext;
+ 			u8 cmd;
+ 		} flags;
+ 	} lower;
+ 	union {
+-		u32 data;
++		__le32 data;
+ 		struct {
+ 			u8 status;     /* Descriptor status */
+ 			u8 popts;      /* Packet Options */
+-			u16 special;
++			__le16 special;
+ 		} fields;
+ 	} upper;
+ };
+diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
+index 928ce82..aaee02e 100644
+--- a/drivers/net/igb/igb_main.c
++++ b/drivers/net/igb/igb_main.c
+@@ -3254,6 +3254,13 @@ quit_polling:
+ 
+ 	return 1;
+ }
++
++static inline u32 get_head(struct igb_ring *tx_ring)
++{
++	void *end = (struct e1000_tx_desc *)tx_ring->desc + tx_ring->count;
++	return le32_to_cpu(*(volatile __le32 *)end);
++}
++
+ /**
+  * igb_clean_tx_irq - Reclaim resources after transmit completes
+  * @adapter: board private structure
+@@ -3275,9 +3282,7 @@ static bool igb_clean_tx_irq(struct igb_adapter *adapter,
+ 	unsigned int total_bytes = 0, total_packets = 0;
+ 
+ 	rmb();
+-	head = *(volatile u32 *)((struct e1000_tx_desc *)tx_ring->desc
+-				 + tx_ring->count);
+-	head = le32_to_cpu(head);
++	head = get_head(tx_ring);
+ 	i = tx_ring->next_to_clean;
+ 	while (1) {
+ 		while (i != head) {
+@@ -3312,9 +3317,7 @@ static bool igb_clean_tx_irq(struct igb_adapter *adapter,
+ 		}
+ 		oldhead = head;
+ 		rmb();
+-		head = *(volatile u32 *)((struct e1000_tx_desc *)tx_ring->desc
+-					 + tx_ring->count);
+-		head = le32_to_cpu(head);
++		head = get_head(tx_ring);
+ 		if (head == oldhead)
+ 			goto done_cleaning;
+ 	}  /* while (1) */
+@@ -3388,7 +3391,7 @@ done_cleaning:
+  * @vlan: descriptor vlan field as written by hardware (no le/be conversion)
+  * @skb: pointer to sk_buff to be indicated to stack
+  **/
+-static void igb_receive_skb(struct igb_adapter *adapter, u8 status, u16 vlan,
++static void igb_receive_skb(struct igb_adapter *adapter, u8 status, __le16 vlan,
+ 			    struct sk_buff *skb)
+ {
+ 	if (adapter->vlgrp && (status & E1000_RXD_STAT_VP))
+@@ -3452,8 +3455,8 @@ static bool igb_clean_rx_irq_adv(struct igb_adapter *adapter,
+ 		 * that case, it fills the header buffer and spills the rest
+ 		 * into the page.
+ 		 */
+-		hlen = le16_to_cpu((rx_desc->wb.lower.lo_dword.hdr_info &
+-		  E1000_RXDADV_HDRBUFLEN_MASK) >> E1000_RXDADV_HDRBUFLEN_SHIFT);
++		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;
+ 
+diff --git a/drivers/net/ixgb/ixgb_main.c b/drivers/net/ixgb/ixgb_main.c
+index 269e6f8..6738b4d 100644
+--- a/drivers/net/ixgb/ixgb_main.c
++++ b/drivers/net/ixgb/ixgb_main.c
+@@ -2088,14 +2088,12 @@ ixgb_alloc_rx_buffers(struct ixgb_adapter *adapter)
+ 	struct ixgb_buffer *buffer_info;
+ 	struct sk_buff *skb;
+ 	unsigned int i;
+-	int num_group_tail_writes;
+ 	long cleancount;
+ 
+ 	i = rx_ring->next_to_use;
+ 	buffer_info = &rx_ring->buffer_info[i];
+ 	cleancount = IXGB_DESC_UNUSED(rx_ring);
+ 
+-	num_group_tail_writes = IXGB_RX_BUFFER_WRITE;
+ 
+ 	/* leave three descriptors unused */
+ 	while(--cleancount > 2) {
+diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
+index 2bc5eaa..7f20a03 100644
+--- a/drivers/net/netxen/netxen_nic.h
++++ b/drivers/net/netxen/netxen_nic.h
+@@ -85,7 +85,7 @@
+ 	(sizeof(struct netxen_cmd_buffer) * adapter->max_tx_desc_count)
+ #define RCV_BUFFSIZE	\
+ 	(sizeof(struct netxen_rx_buffer) * rcv_desc->max_rx_desc_count)
+-#define find_diff_among(a,b,range) ((a)<=(b)?((b)-(a)):((b)+(range)-(a)))
++#define find_diff_among(a,b,range) ((a)<(b)?((b)-(a)):((b)+(range)-(a)))
+ 
+ #define NETXEN_NETDEV_STATUS		0x1
+ #define NETXEN_RCV_PRODUCER_OFFSET	0
+@@ -204,7 +204,7 @@ enum {
+ 			? RCV_DESC_LRO :	\
+ 			(RCV_DESC_NORMAL)))
+ 
+-#define MAX_CMD_DESCRIPTORS		1024
++#define MAX_CMD_DESCRIPTORS		4096
+ #define MAX_RCV_DESCRIPTORS		16384
+ #define MAX_CMD_DESCRIPTORS_HOST	(MAX_CMD_DESCRIPTORS / 4)
+ #define MAX_RCV_DESCRIPTORS_1G		(MAX_RCV_DESCRIPTORS / 4)
+@@ -818,15 +818,8 @@ struct netxen_adapter_stats {
+ 	u64  badskblen;
+ 	u64  nocmddescriptor;
+ 	u64  polled;
+-	u64  uphappy;
+-	u64  updropped;
+-	u64  uplcong;
+-	u64  uphcong;
+-	u64  upmcong;
+-	u64  updunno;
+-	u64  skbfreed;
++	u64  rxdropped;
+ 	u64  txdropped;
+-	u64  txnullskb;
+ 	u64  csummed;
+ 	u64  no_rcv;
+ 	u64  rxbytes;
+@@ -842,7 +835,6 @@ struct netxen_rcv_desc_ctx {
+ 	u32 flags;
+ 	u32 producer;
+ 	u32 rcv_pending;	/* Num of bufs posted in phantom */
+-	u32 rcv_free;		/* Num of bufs in free list */
+ 	dma_addr_t phys_addr;
+ 	struct pci_dev *phys_pdev;
+ 	struct rcv_desc *desc_head;	/* address of rx ring in Phantom */
+@@ -889,8 +881,6 @@ struct netxen_adapter {
+ 	int mtu;
+ 	int portnum;
+ 
+-	spinlock_t tx_lock;
+-	spinlock_t lock;
+ 	struct work_struct watchdog_task;
+ 	struct timer_list watchdog_timer;
+ 	struct work_struct  tx_timeout_task;
+@@ -899,16 +889,12 @@ struct netxen_adapter {
+ 
+ 	u32 cmd_producer;
+ 	__le32 *cmd_consumer;
+-
+ 	u32 last_cmd_consumer;
++
+ 	u32 max_tx_desc_count;
+ 	u32 max_rx_desc_count;
+ 	u32 max_jumbo_rx_desc_count;
+ 	u32 max_lro_rx_desc_count;
+-	/* Num of instances active on cmd buffer ring */
+-	u32 proc_cmd_buf_counter;
+-
+-	u32 num_threads, total_threads;	/*Use to keep track of xmit threads */
+ 
+ 	u32 flags;
+ 	u32 irq;
+@@ -942,6 +928,7 @@ struct netxen_adapter {
+ 	struct pci_dev *ctx_desc_pdev;
+ 	dma_addr_t ctx_desc_phys_addr;
+ 	int intr_scheme;
++	int msi_mode;
+ 	int (*enable_phy_interrupts) (struct netxen_adapter *);
+ 	int (*disable_phy_interrupts) (struct netxen_adapter *);
+ 	void (*handle_phy_intr) (struct netxen_adapter *);
+@@ -1075,12 +1062,10 @@ void netxen_tso_check(struct netxen_adapter *adapter,
+ 		      struct cmd_desc_type0 *desc, struct sk_buff *skb);
+ int netxen_nic_hw_resources(struct netxen_adapter *adapter);
+ void netxen_nic_clear_stats(struct netxen_adapter *adapter);
+-int netxen_nic_rx_has_work(struct netxen_adapter *adapter);
+-int netxen_nic_tx_has_work(struct netxen_adapter *adapter);
+ void netxen_watchdog_task(struct work_struct *work);
+ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx,
+ 			    u32 ringid);
+-int netxen_process_cmd_ring(unsigned long data);
++int netxen_process_cmd_ring(struct netxen_adapter *adapter);
+ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctx, int max);
+ void netxen_nic_set_multi(struct net_device *netdev);
+ int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu);
+diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c
+index 7a876f4..6e98d83 100644
+--- a/drivers/net/netxen/netxen_nic_ethtool.c
++++ b/drivers/net/netxen/netxen_nic_ethtool.c
+@@ -64,15 +64,7 @@ static const struct netxen_nic_stats netxen_nic_gstrings_stats[] = {
+ 	{"bad_skb_len", NETXEN_NIC_STAT(stats.badskblen)},
+ 	{"no_cmd_desc", NETXEN_NIC_STAT(stats.nocmddescriptor)},
+ 	{"polled", NETXEN_NIC_STAT(stats.polled)},
+-	{"uphappy", NETXEN_NIC_STAT(stats.uphappy)},
+-	{"updropped", NETXEN_NIC_STAT(stats.updropped)},
+-	{"uplcong", NETXEN_NIC_STAT(stats.uplcong)},
+-	{"uphcong", NETXEN_NIC_STAT(stats.uphcong)},
+-	{"upmcong", NETXEN_NIC_STAT(stats.upmcong)},
+-	{"updunno", NETXEN_NIC_STAT(stats.updunno)},
+-	{"skb_freed", NETXEN_NIC_STAT(stats.skbfreed)},
+ 	{"tx_dropped", NETXEN_NIC_STAT(stats.txdropped)},
+-	{"tx_null_skb", NETXEN_NIC_STAT(stats.txnullskb)},
+ 	{"csummed", NETXEN_NIC_STAT(stats.csummed)},
+ 	{"no_rcv", NETXEN_NIC_STAT(stats.no_rcv)},
+ 	{"rx_bytes", NETXEN_NIC_STAT(stats.rxbytes)},
+diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h
+index d72f8f8..160f605 100644
+--- a/drivers/net/netxen/netxen_nic_hdr.h
++++ b/drivers/net/netxen/netxen_nic_hdr.h
+@@ -456,6 +456,12 @@ enum {
+ #define ISR_INT_MASK_SLOW	(NETXEN_PCIX_PS_REG(PCIX_INT_MASK))
+ #define ISR_INT_TARGET_STATUS	(NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS))
+ #define ISR_INT_TARGET_MASK	(NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK))
++#define ISR_INT_TARGET_STATUS_F1   (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F1))
++#define ISR_INT_TARGET_MASK_F1     (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F1))
++#define ISR_INT_TARGET_STATUS_F2   (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F2))
++#define ISR_INT_TARGET_MASK_F2     (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F2))
++#define ISR_INT_TARGET_STATUS_F3   (NETXEN_PCIX_PS_REG(PCIX_TARGET_STATUS_F3))
++#define ISR_INT_TARGET_MASK_F3     (NETXEN_PCIX_PS_REG(PCIX_TARGET_MASK_F3))
+ 
+ #define NETXEN_PCI_MAPSIZE	128
+ #define NETXEN_PCI_DDR_NET	(0x00000000UL)
+@@ -662,6 +668,12 @@ enum {
+ 
+ #define PCIX_TARGET_STATUS	(0x10118)
+ #define PCIX_TARGET_MASK	(0x10128)
++#define PCIX_TARGET_STATUS_F1 (0x10160)
++#define PCIX_TARGET_MASK_F1   (0x10170)
++#define PCIX_TARGET_STATUS_F2 (0x10164)
++#define PCIX_TARGET_MASK_F2   (0x10174)
++#define PCIX_TARGET_STATUS_F3 (0x10168)
++#define PCIX_TARGET_MASK_F3   (0x10178)
+ 
+ #define PCIX_MSI_F0		(0x13000)
+ #define PCIX_MSI_F1		(0x13004)
+diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
+index 0135570..05748ca 100644
+--- a/drivers/net/netxen/netxen_nic_hw.c
++++ b/drivers/net/netxen/netxen_nic_hw.c
+@@ -398,6 +398,8 @@ int netxen_nic_hw_resources(struct netxen_adapter *adapter)
+ 		NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_FW));
+ 	printk(KERN_NOTICE "%s: FW capabilities:0x%x\n", netxen_nic_driver_name,
+ 			adapter->intr_scheme);
++	adapter->msi_mode = readl(
++		NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_MSI_MODE_FW));
+ 	DPRINTK(INFO, "Receive Peg ready too. starting stuff\n");
+ 
+ 	addr = netxen_alloc(adapter->ahw.pdev,
+diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
+index 9e38bcb..45fa33e 100644
+--- a/drivers/net/netxen/netxen_nic_init.c
++++ b/drivers/net/netxen/netxen_nic_init.c
+@@ -145,6 +145,8 @@ int netxen_init_firmware(struct netxen_adapter *adapter)
+ 	/* Window 1 call */
+ 	writel(INTR_SCHEME_PERPORT,
+ 	       NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_CAPABILITIES_HOST));
++	writel(MSI_MODE_MULTIFUNC,
++	       NETXEN_CRB_NORMALIZE(adapter, CRB_NIC_MSI_MODE_HOST));
+ 	writel(MPORT_MULTI_FUNCTION_MODE,
+ 	       NETXEN_CRB_NORMALIZE(adapter, CRB_MPORT_MODE));
+ 	writel(PHAN_INITIALIZE_ACK,
+@@ -183,7 +185,6 @@ void netxen_initialize_adapter_sw(struct netxen_adapter *adapter)
+ 		for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
+ 			struct netxen_rx_buffer *rx_buf;
+ 			rcv_desc = &adapter->recv_ctx[ctxid].rcv_desc[ring];
+-			rcv_desc->rcv_free = rcv_desc->max_rx_desc_count;
+ 			rcv_desc->begin_alloc = 0;
+ 			rx_buf = rcv_desc->rx_buf_arr;
+ 			num_rx_bufs = rcv_desc->max_rx_desc_count;
+@@ -974,28 +975,6 @@ int netxen_phantom_init(struct netxen_adapter *adapter, int pegtune_val)
+ 	return 0;
+ }
+ 
+-int netxen_nic_rx_has_work(struct netxen_adapter *adapter)
+-{
+-	int ctx;
+-
+-	for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
+-		struct netxen_recv_context *recv_ctx =
+-		    &(adapter->recv_ctx[ctx]);
+-		u32 consumer;
+-		struct status_desc *desc_head;
+-		struct status_desc *desc;
+-
+-		consumer = recv_ctx->status_rx_consumer;
+-		desc_head = recv_ctx->rcv_status_desc_head;
+-		desc = &desc_head[consumer];
+-
+-		if (netxen_get_sts_owner(desc) & STATUS_OWNER_HOST)
+-			return 1;
+-	}
+-
+-	return 0;
+-}
+-
+ static int netxen_nic_check_temp(struct netxen_adapter *adapter)
+ {
+ 	struct net_device *netdev = adapter->netdev;
+@@ -1038,7 +1017,6 @@ static int netxen_nic_check_temp(struct netxen_adapter *adapter)
+ 
+ void netxen_watchdog_task(struct work_struct *work)
+ {
+-	struct net_device *netdev;
+ 	struct netxen_adapter *adapter =
+ 		container_of(work, struct netxen_adapter, watchdog_task);
+ 
+@@ -1048,20 +1026,6 @@ void netxen_watchdog_task(struct work_struct *work)
+ 	if (adapter->handle_phy_intr)
+ 		adapter->handle_phy_intr(adapter);
+ 
+-	netdev = adapter->netdev;
+-	if ((netif_running(netdev)) && !netif_carrier_ok(netdev) &&
+-			netxen_nic_link_ok(adapter) ) {
+-		printk(KERN_INFO "%s %s (port %d), Link is up\n",
+-			       netxen_nic_driver_name, netdev->name, adapter->portnum);
+-		netif_carrier_on(netdev);
+-		netif_wake_queue(netdev);
+-	} else if(!(netif_running(netdev)) && netif_carrier_ok(netdev)) {
+-		printk(KERN_ERR "%s %s Link is Down\n",
+-				netxen_nic_driver_name, netdev->name);
+-		netif_carrier_off(netdev);
+-		netif_stop_queue(netdev);
+-	}
+-
+ 	mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ);
+ }
+ 
+@@ -1125,7 +1089,7 @@ static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
+ 	skb = (struct sk_buff *)buffer->skb;
+ 
+ 	if (likely(adapter->rx_csum &&
+-				netxen_get_sts_status(sts_data) == STATUS_CKSUM_OK)) {
++			netxen_get_sts_status(sts_data) == STATUS_CKSUM_OK)) {
+ 		adapter->stats.csummed++;
+ 		skb->ip_summed = CHECKSUM_UNNECESSARY;
+ 	} else
+@@ -1142,40 +1106,8 @@ static void netxen_process_rcv(struct netxen_adapter *adapter, int ctxid,
+ 	skb->protocol = eth_type_trans(skb, netdev);
+ 
+ 	ret = netif_receive_skb(skb);
+-
+-	/*
+-	 * RH: Do we need these stats on a regular basis. Can we get it from
+-	 * Linux stats.
+-	 */
+-	switch (ret) {
+-	case NET_RX_SUCCESS:
+-		adapter->stats.uphappy++;
+-		break;
+-
+-	case NET_RX_CN_LOW:
+-		adapter->stats.uplcong++;
+-		break;
+-
+-	case NET_RX_CN_MOD:
+-		adapter->stats.upmcong++;
+-		break;
+-
+-	case NET_RX_CN_HIGH:
+-		adapter->stats.uphcong++;
+-		break;
+-
+-	case NET_RX_DROP:
+-		adapter->stats.updropped++;
+-		break;
+-
+-	default:
+-		adapter->stats.updunno++;
+-		break;
+-	}
+-
+ 	netdev->last_rx = jiffies;
+ 
+-	rcv_desc->rcv_free++;
+ 	rcv_desc->rcv_pending--;
+ 
+ 	/*
+@@ -1200,13 +1132,6 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max)
+ 	u32 producer = 0;
+ 	int count = 0, ring;
+ 
+-	DPRINTK(INFO, "procesing receive\n");
+-	/*
+-	 * we assume in this case that there is only one port and that is
+-	 * port #1...changes need to be done in firmware to indicate port
+-	 * number as part of the descriptor. This way we will be able to get
+-	 * the netdev which is associated with that device.
+-	 */
+ 	while (count < max) {
+ 		desc = &desc_head[consumer];
+ 		if (!(netxen_get_sts_owner(desc) & STATUS_OWNER_HOST)) {
+@@ -1219,11 +1144,8 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max)
+ 		consumer = (consumer + 1) & (adapter->max_rx_desc_count - 1);
+ 		count++;
+ 	}
+-	if (count) {
+-		for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++) {
+-			netxen_post_rx_buffers_nodb(adapter, ctxid, ring);
+-		}
+-	}
++	for (ring = 0; ring < NUM_RCV_DESC_RINGS; ring++)
++		netxen_post_rx_buffers_nodb(adapter, ctxid, ring);
+ 
+ 	/* update the consumer index in phantom */
+ 	if (count) {
+@@ -1233,108 +1155,60 @@ u32 netxen_process_rcv_ring(struct netxen_adapter *adapter, int ctxid, int max)
+ 		/* Window = 1 */
+ 		writel(consumer,
+ 		       NETXEN_CRB_NORMALIZE(adapter,
+-					    recv_crb_registers[adapter->portnum].
++				    recv_crb_registers[adapter->portnum].
+ 					    crb_rcv_status_consumer));
+-		wmb();
+ 	}
+ 
+ 	return count;
+ }
+ 
+ /* Process Command status ring */
+-int netxen_process_cmd_ring(unsigned long data)
++int netxen_process_cmd_ring(struct netxen_adapter *adapter)
+ {
+-	u32 last_consumer;
+-	u32 consumer;
+-	struct netxen_adapter *adapter = (struct netxen_adapter *)data;
+-	int count1 = 0;
+-	int count2 = 0;
++	u32 last_consumer, consumer;
++	int count = 0, i;
+ 	struct netxen_cmd_buffer *buffer;
+-	struct pci_dev *pdev;
++	struct pci_dev *pdev = adapter->pdev;
++	struct net_device *netdev = adapter->netdev;
+ 	struct netxen_skb_frag *frag;
+-	u32 i;
+-	int done;
++	int done = 0;
+ 
+-	spin_lock(&adapter->tx_lock);
+ 	last_consumer = adapter->last_cmd_consumer;
+-	DPRINTK(INFO, "procesing xmit complete\n");
+-	/* we assume in this case that there is only one port and that is
+-	 * port #1...changes need to be done in firmware to indicate port
+-	 * number as part of the descriptor. This way we will be able to get
+-	 * the netdev which is associated with that device.
+-	 */
+-
+ 	consumer = le32_to_cpu(*(adapter->cmd_consumer));
+-	if (last_consumer == consumer) {	/* Ring is empty    */
+-		DPRINTK(INFO, "last_consumer %d == consumer %d\n",
+-			last_consumer, consumer);
+-		spin_unlock(&adapter->tx_lock);
+-		return 1;
+-	}
+-
+-	adapter->proc_cmd_buf_counter++;
+-	/*
+-	 * Not needed - does not seem to be used anywhere.
+-	 * adapter->cmd_consumer = consumer;
+-	 */
+-	spin_unlock(&adapter->tx_lock);
+ 
+-	while ((last_consumer != consumer) && (count1 < MAX_STATUS_HANDLE)) {
++	while (last_consumer != consumer) {
+ 		buffer = &adapter->cmd_buf_arr[last_consumer];
+-		pdev = adapter->pdev;
+ 		if (buffer->skb) {
+ 			frag = &buffer->frag_array[0];
+ 			pci_unmap_single(pdev, frag->dma, frag->length,
+ 					 PCI_DMA_TODEVICE);
+ 			frag->dma = 0ULL;
+ 			for (i = 1; i < buffer->frag_count; i++) {
+-				DPRINTK(INFO, "getting fragment no %d\n", i);
+ 				frag++;	/* Get the next frag */
+ 				pci_unmap_page(pdev, frag->dma, frag->length,
+ 					       PCI_DMA_TODEVICE);
+ 				frag->dma = 0ULL;
+ 			}
+ 
+-			adapter->stats.skbfreed++;
++			adapter->stats.xmitfinished++;
+ 			dev_kfree_skb_any(buffer->skb);
+ 			buffer->skb = NULL;
+-		} else if (adapter->proc_cmd_buf_counter == 1) {
+-			adapter->stats.txnullskb++;
+-		}
+-		if (unlikely(netif_queue_stopped(adapter->netdev)
+-			     && netif_carrier_ok(adapter->netdev))
+-		    && ((jiffies - adapter->netdev->trans_start) >
+-			adapter->netdev->watchdog_timeo)) {
+-			SCHEDULE_WORK(&adapter->tx_timeout_task);
+ 		}
+ 
+ 		last_consumer = get_next_index(last_consumer,
+ 					       adapter->max_tx_desc_count);
+-		count1++;
++		if (++count >= MAX_STATUS_HANDLE)
++			break;
+ 	}
+ 
+-	count2 = 0;
+-	spin_lock(&adapter->tx_lock);
+-	if ((--adapter->proc_cmd_buf_counter) == 0) {
++	if (count) {
+ 		adapter->last_cmd_consumer = last_consumer;
+-		while ((adapter->last_cmd_consumer != consumer)
+-		       && (count2 < MAX_STATUS_HANDLE)) {
+-			buffer =
+-			    &adapter->cmd_buf_arr[adapter->last_cmd_consumer];
+-			count2++;
+-			if (buffer->skb)
+-				break;
+-			else
+-				adapter->last_cmd_consumer =
+-				    get_next_index(adapter->last_cmd_consumer,
+-						   adapter->max_tx_desc_count);
+-		}
+-	}
+-	if (count1 || count2) {
+-		if (netif_queue_stopped(adapter->netdev)
+-		    && (adapter->flags & NETXEN_NETDEV_STATUS)) {
+-			netif_wake_queue(adapter->netdev);
+-			adapter->flags &= ~NETXEN_NETDEV_STATUS;
++		smp_mb();
++		if (netif_queue_stopped(netdev) && netif_running(netdev)) {
++			netif_tx_lock(netdev);
++			netif_wake_queue(netdev);
++			smp_mb();
++			netif_tx_unlock(netdev);
+ 		}
+ 	}
+ 	/*
+@@ -1350,16 +1224,9 @@ int netxen_process_cmd_ring(unsigned long data)
+ 	 * There is still a possible race condition and the host could miss an
+ 	 * interrupt. The card has to take care of this.
+ 	 */
+-	if (adapter->last_cmd_consumer == consumer &&
+-	    (((adapter->cmd_producer + 1) %
+-	      adapter->max_tx_desc_count) == adapter->last_cmd_consumer)) {
+-		consumer = le32_to_cpu(*(adapter->cmd_consumer));
+-	}
+-	done = (adapter->last_cmd_consumer == consumer);
++	consumer = le32_to_cpu(*(adapter->cmd_consumer));
++	done = (last_consumer == consumer);
+ 
+-	spin_unlock(&adapter->tx_lock);
+-	DPRINTK(INFO, "last consumer is %d in %s\n", last_consumer,
+-		__FUNCTION__);
+ 	return (done);
+ }
+ 
+@@ -1433,8 +1300,6 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
+ 		rcv_desc->begin_alloc = index;
+ 		rcv_desc->rcv_pending += count;
+ 		rcv_desc->producer = producer;
+-		if (rcv_desc->rcv_free >= 32) {
+-			rcv_desc->rcv_free = 0;
+ 			/* Window = 1 */
+ 			writel((producer - 1) &
+ 			       (rcv_desc->max_rx_desc_count - 1),
+@@ -1458,8 +1323,6 @@ void netxen_post_rx_buffers(struct netxen_adapter *adapter, u32 ctx, u32 ringid)
+ 			writel(msg,
+ 			       DB_NORMALIZE(adapter,
+ 					    NETXEN_RCV_PRODUCER_OFFSET));
+-			wmb();
+-		}
+ 	}
+ }
+ 
+@@ -1523,8 +1386,6 @@ static void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,
+ 		rcv_desc->begin_alloc = index;
+ 		rcv_desc->rcv_pending += count;
+ 		rcv_desc->producer = producer;
+-		if (rcv_desc->rcv_free >= 32) {
+-			rcv_desc->rcv_free = 0;
+ 			/* Window = 1 */
+ 			writel((producer - 1) &
+ 			       (rcv_desc->max_rx_desc_count - 1),
+@@ -1534,21 +1395,9 @@ static void netxen_post_rx_buffers_nodb(struct netxen_adapter *adapter,
+ 						    rcv_desc_crb[ringid].
+ 						    crb_rcv_producer_offset));
+ 			wmb();
+-		}
+ 	}
+ }
+ 
+-int netxen_nic_tx_has_work(struct netxen_adapter *adapter)
+-{
+-	if (find_diff_among(adapter->last_cmd_consumer,
+-			    adapter->cmd_producer,
+-			    adapter->max_tx_desc_count) > 0)
+-		return 1;
+-
+-	return 0;
+-}
+-
+-
+ void netxen_nic_clear_stats(struct netxen_adapter *adapter)
+ {
+ 	memset(&adapter->stats, 0, sizeof(adapter->stats));
+diff --git a/drivers/net/netxen/netxen_nic_isr.c b/drivers/net/netxen/netxen_nic_isr.c
+index 48a404a..c81313b 100644
+--- a/drivers/net/netxen/netxen_nic_isr.c
++++ b/drivers/net/netxen/netxen_nic_isr.c
+@@ -59,7 +59,7 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
+ 	/* packet transmit problems */
+ 	stats->tx_errors = adapter->stats.nocmddescriptor;
+ 	/* no space in linux buffers    */
+-	stats->rx_dropped = adapter->stats.updropped;
++	stats->rx_dropped = adapter->stats.rxdropped;
+ 	/* no space available in linux  */
+ 	stats->tx_dropped = adapter->stats.txdropped;
+ 
+@@ -193,14 +193,14 @@ int netxen_nic_link_ok(struct netxen_adapter *adapter)
+ void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter)
+ {
+ 	struct net_device *netdev = adapter->netdev;
+-	u32 val, val1;
++	u32 val;
+ 
+ 	/* WINDOW = 1 */
+ 	val = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_XG_STATE));
+ 	val >>= (physical_port[adapter->portnum] * 8);
+-	val1 = val & 0xff;
++	val &= 0xff;
+ 
+-	if (adapter->ahw.xg_linkup == 1 && val1 != XG_LINK_UP) {
++	if (adapter->ahw.xg_linkup == 1 && val != XG_LINK_UP) {
+ 		printk(KERN_INFO "%s: %s NIC Link is down\n",
+ 		       netxen_nic_driver_name, netdev->name);
+ 		adapter->ahw.xg_linkup = 0;
+@@ -208,16 +208,7 @@ void netxen_nic_xgbe_handle_phy_intr(struct netxen_adapter *adapter)
+ 			netif_carrier_off(netdev);
+ 			netif_stop_queue(netdev);
+ 		}
+-		/* read twice to clear sticky bits */
+-		/* WINDOW = 0 */
+-		netxen_nic_read_w0(adapter, NETXEN_NIU_XG_STATUS, &val1);
+-		netxen_nic_read_w0(adapter, NETXEN_NIU_XG_STATUS, &val1);
+-
+-		if ((val & 0xffb) != 0xffb) {
+-			printk(KERN_INFO "%s ISR: Sync/Align BAD: 0x%08x\n",
+-			       netxen_nic_driver_name, val1);
+-		}
+-	} else if (adapter->ahw.xg_linkup == 0 && val1 == XG_LINK_UP) {
++	} else if (adapter->ahw.xg_linkup == 0 && val == XG_LINK_UP) {
+ 		printk(KERN_INFO "%s: %s NIC Link is up\n",
+ 		       netxen_nic_driver_name, netdev->name);
+ 		adapter->ahw.xg_linkup = 1;
+diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
+index 9737eae..a8fb439 100644
+--- a/drivers/net/netxen/netxen_nic_main.c
++++ b/drivers/net/netxen/netxen_nic_main.c
+@@ -63,12 +63,12 @@ static int netxen_nic_xmit_frame(struct sk_buff *, struct net_device *);
+ static void netxen_tx_timeout(struct net_device *netdev);
+ static void netxen_tx_timeout_task(struct work_struct *work);
+ static void netxen_watchdog(unsigned long);
+-static int netxen_handle_int(struct netxen_adapter *, struct net_device *);
+ static int netxen_nic_poll(struct napi_struct *napi, int budget);
+ #ifdef CONFIG_NET_POLL_CONTROLLER
+ static void netxen_nic_poll_controller(struct net_device *netdev);
+ #endif
+ static irqreturn_t netxen_intr(int irq, void *data);
++static irqreturn_t netxen_msi_intr(int irq, void *data);
+ 
+ int physical_port[] = {0, 1, 2, 3};
+ 
+@@ -149,33 +149,30 @@ static void netxen_nic_update_cmd_consumer(struct netxen_adapter *adapter,
+ 
+ #define	ADAPTER_LIST_SIZE 12
+ 
++static uint32_t msi_tgt_status[4] = {
++	ISR_INT_TARGET_STATUS, ISR_INT_TARGET_STATUS_F1,
++	ISR_INT_TARGET_STATUS_F2, ISR_INT_TARGET_STATUS_F3
++};
++
++static uint32_t sw_int_mask[4] = {
++	CRB_SW_INT_MASK_0, CRB_SW_INT_MASK_1,
++	CRB_SW_INT_MASK_2, CRB_SW_INT_MASK_3
++};
++
+ static void netxen_nic_disable_int(struct netxen_adapter *adapter)
+ {
+-	uint32_t	mask = 0x7ff;
++	u32 mask = 0x7ff;
+ 	int retries = 32;
++	int port = adapter->portnum;
++	int pci_fn = adapter->ahw.pci_func;
+ 
+-	DPRINTK(1, INFO, "Entered ISR Disable \n");
+-
+-	switch (adapter->portnum) {
+-	case 0:
+-		writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0));
+-		break;
+-	case 1:
+-		writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1));
+-		break;
+-	case 2:
+-		writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2));
+-		break;
+-	case 3:
+-		writel(0x0, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3));
+-		break;
+-	}
++	if (adapter->msi_mode != MSI_MODE_MULTIFUNC)
++		writel(0x0, NETXEN_CRB_NORMALIZE(adapter, sw_int_mask[port]));
+ 
+ 	if (adapter->intr_scheme != -1 &&
+ 	    adapter->intr_scheme != INTR_SCHEME_PERPORT)
+ 		writel(mask,PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
+ 
+-	/* Window = 0 or 1 */
+ 	if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+ 		do {
+ 			writel(0xffffffff,
+@@ -190,14 +187,18 @@ static void netxen_nic_disable_int(struct netxen_adapter *adapter)
+ 			printk(KERN_NOTICE "%s: Failed to disable interrupt completely\n",
+ 					netxen_nic_driver_name);
+ 		}
++	} else {
++		if (adapter->msi_mode == MSI_MODE_MULTIFUNC) {
++			writel(0xffffffff, PCI_OFFSET_SECOND_RANGE(adapter,
++						msi_tgt_status[pci_fn]));
++		}
+ 	}
+-
+-	DPRINTK(1, INFO, "Done with Disable Int\n");
+ }
+ 
+ static void netxen_nic_enable_int(struct netxen_adapter *adapter)
+ {
+ 	u32 mask;
++	int port = adapter->portnum;
+ 
+ 	DPRINTK(1, INFO, "Entered ISR Enable \n");
+ 
+@@ -218,20 +219,7 @@ static void netxen_nic_enable_int(struct netxen_adapter *adapter)
+ 		writel(mask, PCI_OFFSET_SECOND_RANGE(adapter, ISR_INT_MASK));
+ 	}
+ 
+-	switch (adapter->portnum) {
+-	case 0:
+-		writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_0));
+-		break;
+-	case 1:
+-		writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_1));
+-		break;
+-	case 2:
+-		writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_2));
+-		break;
+-	case 3:
+-		writel(0x1, NETXEN_CRB_NORMALIZE(adapter, CRB_SW_INT_MASK_3));
+-		break;
+-	}
++	writel(0x1, NETXEN_CRB_NORMALIZE(adapter, sw_int_mask[port]));
+ 
+ 	if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+ 		mask = 0xbff;
+@@ -328,7 +316,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 
+ 	adapter->ahw.pdev = pdev;
+ 	adapter->ahw.pci_func  = pci_func_id;
+-	spin_lock_init(&adapter->tx_lock);
+ 
+ 	/* remap phys address */
+ 	mem_base = pci_resource_start(pdev, 0);	/* 0 is for BAR 0 */
+@@ -401,6 +388,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 
+ 	/* this will be read from FW later */
+ 	adapter->intr_scheme = -1;
++	adapter->msi_mode = -1;
+ 
+ 	/* This will be reset for mezz cards  */
+ 	adapter->portnum = pci_func_id;
+@@ -415,7 +403,7 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	netdev->set_mac_address    = netxen_nic_set_mac;
+ 	netdev->change_mtu	   = netxen_nic_change_mtu;
+ 	netdev->tx_timeout	   = netxen_tx_timeout;
+-	netdev->watchdog_timeo     = HZ;
++	netdev->watchdog_timeo     = 2*HZ;
+ 
+ 	netxen_nic_change_mtu(netdev, netdev->mtu);
+ 
+@@ -543,7 +531,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	adapter->watchdog_timer.data = (unsigned long)adapter;
+ 	INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task);
+ 	adapter->ahw.pdev = pdev;
+-	adapter->proc_cmd_buf_counter = 0;
+ 	adapter->ahw.revision_id = pdev->revision;
+ 
+ 	/* make sure Window == 1 */
+@@ -833,6 +820,8 @@ static int netxen_nic_open(struct net_device *netdev)
+ 	struct netxen_adapter *adapter = (struct netxen_adapter *)netdev->priv;
+ 	int err = 0;
+ 	int ctx, ring;
++	irq_handler_t handler;
++	unsigned long flags = IRQF_SAMPLE_RANDOM;
+ 
+ 	if (adapter->is_up != NETXEN_ADAPTER_UP_MAGIC) {
+ 		err = netxen_init_firmware(adapter);
+@@ -856,9 +845,14 @@ static int netxen_nic_open(struct net_device *netdev)
+ 				netxen_post_rx_buffers(adapter, ctx, ring);
+ 		}
+ 		adapter->irq = adapter->ahw.pdev->irq;
+-		err = request_irq(adapter->ahw.pdev->irq, netxen_intr,
+-				  IRQF_SHARED|IRQF_SAMPLE_RANDOM, netdev->name,
+-				  adapter);
++		if (adapter->flags & NETXEN_NIC_MSI_ENABLED)
++			handler = netxen_msi_intr;
++		else {
++			flags |= IRQF_SHARED;
++			handler = netxen_intr;
++		}
++		err = request_irq(adapter->irq, handler,
++				  flags, netdev->name, adapter);
+ 		if (err) {
+ 			printk(KERN_ERR "request_irq failed with: %d\n", err);
+ 			netxen_free_hw_resources(adapter);
+@@ -867,21 +861,12 @@ static int netxen_nic_open(struct net_device *netdev)
+ 
+ 		adapter->is_up = NETXEN_ADAPTER_UP_MAGIC;
+ 	}
+-	if (!adapter->driver_mismatch)
+-		mod_timer(&adapter->watchdog_timer, jiffies);
+-
+-	napi_enable(&adapter->napi);
+-
+-	netxen_nic_enable_int(adapter);
+-
+ 	/* Done here again so that even if phantom sw overwrote it,
+ 	 * we set it */
+ 	if (adapter->init_port
+ 	    && adapter->init_port(adapter, adapter->portnum) != 0) {
+-	    del_timer_sync(&adapter->watchdog_timer);
+ 		printk(KERN_ERR "%s: Failed to initialize port %d\n",
+ 				netxen_nic_driver_name, adapter->portnum);
+-		napi_disable(&adapter->napi);
+ 		return -EIO;
+ 	}
+ 	if (adapter->macaddr_set)
+@@ -894,6 +879,12 @@ static int netxen_nic_open(struct net_device *netdev)
+ 		adapter->set_mtu(adapter, netdev->mtu);
+ 
+ 	if (!adapter->driver_mismatch)
++		mod_timer(&adapter->watchdog_timer, jiffies);
++
++	napi_enable(&adapter->napi);
++	netxen_nic_enable_int(adapter);
++
++	if (!adapter->driver_mismatch)
+ 		netif_start_queue(netdev);
+ 
+ 	return 0;
+@@ -958,41 +949,17 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ 	struct netxen_skb_frag *buffrag;
+ 	unsigned int i;
+ 
+-	u32 producer = 0;
++	u32 producer, consumer;
+ 	u32 saved_producer = 0;
+ 	struct cmd_desc_type0 *hwdesc;
+ 	int k;
+ 	struct netxen_cmd_buffer *pbuf = NULL;
+-	static int dropped_packet = 0;
+ 	int frag_count;
+-	u32 local_producer = 0;
+-	u32 max_tx_desc_count = 0;
+-	u32 last_cmd_consumer = 0;
+ 	int no_of_desc;
++	u32 num_txd = adapter->max_tx_desc_count;
+ 
+-	adapter->stats.xmitcalled++;
+ 	frag_count = skb_shinfo(skb)->nr_frags + 1;
+ 
+-	if (unlikely(skb->len <= 0)) {
+-		dev_kfree_skb_any(skb);
+-		adapter->stats.badskblen++;
+-		return NETDEV_TX_OK;
+-	}
+-
+-	if (frag_count > MAX_BUFFERS_PER_CMD) {
+-		printk("%s: %s netxen_nic_xmit_frame: frag_count (%d) "
+-		       "too large, can handle only %d frags\n",
+-		       netxen_nic_driver_name, netdev->name,
+-		       frag_count, MAX_BUFFERS_PER_CMD);
+-		adapter->stats.txdropped++;
+-		if ((++dropped_packet & 0xff) == 0xff)
+-			printk("%s: %s droppped packets = %d\n",
+-			       netxen_nic_driver_name, netdev->name,
+-			       dropped_packet);
+-
+-		return NETDEV_TX_OK;
+-	}
+-
+ 	/* There 4 fragments per descriptor */
+ 	no_of_desc = (frag_count + 3) >> 2;
+ 	if (netdev->features & NETIF_F_TSO) {
+@@ -1007,27 +974,16 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ 		}
+ 	}
+ 
+-	spin_lock_bh(&adapter->tx_lock);
+-	if (adapter->total_threads >= MAX_XMIT_PRODUCERS) {
+-		goto out_requeue;
+-	}
+-	local_producer = adapter->cmd_producer;
+-	k = adapter->cmd_producer;
+-	max_tx_desc_count = adapter->max_tx_desc_count;
+-	last_cmd_consumer = adapter->last_cmd_consumer;
+-	if ((k + no_of_desc) >=
+-	    ((last_cmd_consumer <= k) ? last_cmd_consumer + max_tx_desc_count :
+-	     last_cmd_consumer)) {
+-		goto out_requeue;
++	producer = adapter->cmd_producer;
++	smp_mb();
++	consumer = adapter->last_cmd_consumer;
++	if ((no_of_desc+2) > find_diff_among(producer, consumer, num_txd)) {
++		netif_stop_queue(netdev);
++		smp_mb();
++		return NETDEV_TX_BUSY;
+ 	}
+-	k = get_index_range(k, max_tx_desc_count, no_of_desc);
+-	adapter->cmd_producer = k;
+-	adapter->total_threads++;
+-	adapter->num_threads++;
+ 
+-	spin_unlock_bh(&adapter->tx_lock);
+ 	/* Copy the descriptors into the hardware    */
+-	producer = local_producer;
+ 	saved_producer = producer;
+ 	hwdesc = &hw->cmd_desc_head[producer];
+ 	memset(hwdesc, 0, sizeof(struct cmd_desc_type0));
+@@ -1067,8 +1023,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ 		/* move to next desc. if there is a need */
+ 		if ((i & 0x3) == 0) {
+ 			k = 0;
+-			producer = get_next_index(producer,
+-						  adapter->max_tx_desc_count);
++			producer = get_next_index(producer, num_txd);
+ 			hwdesc = &hw->cmd_desc_head[producer];
+ 			memset(hwdesc, 0, sizeof(struct cmd_desc_type0));
+ 			pbuf = &adapter->cmd_buf_arr[producer];
+@@ -1086,7 +1041,6 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ 		buffrag->dma = temp_dma;
+ 		buffrag->length = temp_len;
+ 
+-		DPRINTK(INFO, "for loop. i=%d k=%d\n", i, k);
+ 		switch (k) {
+ 		case 0:
+ 			hwdesc->buffer1_length = cpu_to_le16(temp_len);
+@@ -1107,7 +1061,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ 		}
+ 		frag++;
+ 	}
+-	producer = get_next_index(producer, adapter->max_tx_desc_count);
++	producer = get_next_index(producer, num_txd);
+ 
+ 	/* might change opcode to TX_TCP_LSO */
+ 	netxen_tso_check(adapter, &hw->cmd_desc_head[saved_producer], skb);
+@@ -1134,7 +1088,7 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ 		/* copy the first 64 bytes */
+ 		memcpy(((void *)hwdesc) + 2,
+ 		       (void *)(skb->data), first_hdr_len);
+-		producer = get_next_index(producer, max_tx_desc_count);
++		producer = get_next_index(producer, num_txd);
+ 
+ 		if (more_hdr) {
+ 			hwdesc = &hw->cmd_desc_head[producer];
+@@ -1147,35 +1101,19 @@ static int netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
+ 							 hwdesc,
+ 							 (hdr_len -
+ 							  first_hdr_len));
+-			producer = get_next_index(producer, max_tx_desc_count);
++			producer = get_next_index(producer, num_txd);
+ 		}
+ 	}
+ 
+-	spin_lock_bh(&adapter->tx_lock);
++	adapter->cmd_producer = producer;
+ 	adapter->stats.txbytes += skb->len;
+ 
+-	/* Code to update the adapter considering how many producer threads
+-	   are currently working */
+-	if ((--adapter->num_threads) == 0) {
+-		/* This is the last thread */
+-		u32 crb_producer = adapter->cmd_producer;
+-		netxen_nic_update_cmd_producer(adapter, crb_producer);
+-		wmb();
+-		adapter->total_threads = 0;
+-	}
++	netxen_nic_update_cmd_producer(adapter, adapter->cmd_producer);
+ 
+-	adapter->stats.xmitfinished++;
++	adapter->stats.xmitcalled++;
+ 	netdev->trans_start = jiffies;
+ 
+-	spin_unlock_bh(&adapter->tx_lock);
+ 	return NETDEV_TX_OK;
+-
+-out_requeue:
+-	netif_stop_queue(netdev);
+-	adapter->flags |= NETXEN_NETDEV_STATUS;
+-
+-	spin_unlock_bh(&adapter->tx_lock);
+-	return NETDEV_TX_BUSY;
+ }
+ 
+ static void netxen_watchdog(unsigned long v)
+@@ -1200,87 +1138,60 @@ static void netxen_tx_timeout_task(struct work_struct *work)
+ 	printk(KERN_ERR "%s %s: transmit timeout, resetting.\n",
+ 	       netxen_nic_driver_name, adapter->netdev->name);
+ 
+-	netxen_nic_close(adapter->netdev);
+-	netxen_nic_open(adapter->netdev);
++	netxen_nic_disable_int(adapter);
++	napi_disable(&adapter->napi);
++
+ 	adapter->netdev->trans_start = jiffies;
++
++	napi_enable(&adapter->napi);
++	netxen_nic_enable_int(adapter);
+ 	netif_wake_queue(adapter->netdev);
+ }
+ 
+-static int
+-netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev)
++static inline void
++netxen_handle_int(struct netxen_adapter *adapter)
+ {
+-	u32 ret = 0;
+-
+-	DPRINTK(INFO, "Entered handle ISR\n");
+-	adapter->stats.ints++;
+-
+ 	netxen_nic_disable_int(adapter);
+-
+-	if (netxen_nic_rx_has_work(adapter) || netxen_nic_tx_has_work(adapter)) {
+-		if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
+-			/*
+-			 * Interrupts are already disabled.
+-			 */
+-			__netif_rx_schedule(netdev, &adapter->napi);
+-		} else {
+-			static unsigned int intcount = 0;
+-			if ((++intcount & 0xfff) == 0xfff)
+-				DPRINTK(KERN_ERR
+-				       "%s: %s interrupt %d while in poll\n",
+-				       netxen_nic_driver_name, netdev->name,
+-				       intcount);
+-		}
+-		ret = 1;
+-	}
+-
+-	if (ret == 0) {
+-		netxen_nic_enable_int(adapter);
+-	}
+-
+-	return ret;
++	napi_schedule(&adapter->napi);
+ }
+ 
+-/*
+- * netxen_intr - Interrupt Handler
+- * @irq: interrupt number
+- * data points to adapter stucture (which may be handling more than 1 port
+- */
+ irqreturn_t netxen_intr(int irq, void *data)
+ {
+ 	struct netxen_adapter *adapter = data;
+-	struct net_device *netdev = adapter->netdev;
+ 	u32 our_int = 0;
+ 
+-	if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+-		our_int = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
+-		/* not our interrupt */
+-		if ((our_int & (0x80 << adapter->portnum)) == 0)
+-			return IRQ_NONE;
+-	}
++	our_int = readl(NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
++	/* not our interrupt */
++	if ((our_int & (0x80 << adapter->portnum)) == 0)
++		return IRQ_NONE;
+ 
+ 	if (adapter->intr_scheme == INTR_SCHEME_PERPORT) {
+ 		/* claim interrupt */
+-		if (!(adapter->flags & NETXEN_NIC_MSI_ENABLED)) {
+-			writel(our_int & ~((u32)(0x80 << adapter->portnum)),
++		writel(our_int & ~((u32)(0x80 << adapter->portnum)),
+ 			NETXEN_CRB_NORMALIZE(adapter, CRB_INT_VECTOR));
+-		}
+ 	}
+ 
+-	if (netif_running(netdev))
+-		netxen_handle_int(adapter, netdev);
++	netxen_handle_int(adapter);
+ 
+ 	return IRQ_HANDLED;
+ }
+ 
++irqreturn_t netxen_msi_intr(int irq, void *data)
++{
++	struct netxen_adapter *adapter = data;
++
++	netxen_handle_int(adapter);
++	return IRQ_HANDLED;
++}
++
+ static int netxen_nic_poll(struct napi_struct *napi, int budget)
+ {
+ 	struct netxen_adapter *adapter = container_of(napi, struct netxen_adapter, napi);
+-	struct net_device *netdev = adapter->netdev;
+-	int done = 1;
++	int tx_complete;
+ 	int ctx;
+ 	int work_done;
+ 
+-	DPRINTK(INFO, "polling for %d descriptors\n", *budget);
++	tx_complete = netxen_process_cmd_ring(adapter);
+ 
+ 	work_done = 0;
+ 	for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) {
+@@ -1300,16 +1211,8 @@ static int netxen_nic_poll(struct napi_struct *napi, int budget)
+ 						     budget / MAX_RCV_CTX);
+ 	}
+ 
+-	if (work_done >= budget)
+-		done = 0;
+-
+-	if (netxen_process_cmd_ring((unsigned long)adapter) == 0)
+-		done = 0;
+-
+-	DPRINTK(INFO, "new work_done: %d work_to_do: %d\n",
+-		work_done, work_to_do);
+-	if (done) {
+-		netif_rx_complete(netdev, napi);
++	if ((work_done < budget) && tx_complete) {
++		netif_rx_complete(adapter->netdev, &adapter->napi);
+ 		netxen_nic_enable_int(adapter);
+ 	}
+ 
+diff --git a/drivers/net/netxen/netxen_nic_phan_reg.h b/drivers/net/netxen/netxen_nic_phan_reg.h
+index ffa3b72..a566b50 100644
+--- a/drivers/net/netxen/netxen_nic_phan_reg.h
++++ b/drivers/net/netxen/netxen_nic_phan_reg.h
+@@ -126,8 +126,11 @@
+  */
+ #define CRB_NIC_CAPABILITIES_HOST	NETXEN_NIC_REG(0x1a8)
+ #define CRB_NIC_CAPABILITIES_FW	  	NETXEN_NIC_REG(0x1dc)
++#define CRB_NIC_MSI_MODE_HOST		NETXEN_NIC_REG(0x270)
++#define CRB_NIC_MSI_MODE_FW	  		NETXEN_NIC_REG(0x274)
+ 
+ #define INTR_SCHEME_PERPORT	      	0x1
++#define MSI_MODE_MULTIFUNC	      	0x1
+ 
+ /* used for ethtool tests */
+ #define CRB_SCRATCHPAD_TEST	    NETXEN_NIC_REG(0x280)
+diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
+index f057407..3353991 100644
+--- a/drivers/net/phy/marvell.c
++++ b/drivers/net/phy/marvell.c
+@@ -58,9 +58,25 @@
+ #define MII_M1111_RX_DELAY		0x80
+ #define MII_M1111_TX_DELAY		0x2
+ #define MII_M1111_PHY_EXT_SR		0x1b
+-#define MII_M1111_HWCFG_MODE_MASK	0xf
+-#define MII_M1111_HWCFG_MODE_RGMII	0xb
++
++#define MII_M1111_HWCFG_MODE_MASK		0xf
++#define MII_M1111_HWCFG_MODE_COPPER_RGMII	0xb
++#define MII_M1111_HWCFG_MODE_FIBER_RGMII	0x3
+ #define MII_M1111_HWCFG_MODE_SGMII_NO_CLK	0x4
++#define MII_M1111_HWCFG_FIBER_COPPER_AUTO	0x8000
++#define MII_M1111_HWCFG_FIBER_COPPER_RES	0x2000
++
++#define MII_M1111_COPPER		0
++#define MII_M1111_FIBER			1
++
++#define MII_M1011_PHY_STATUS		0x11
++#define MII_M1011_PHY_STATUS_1000	0x8000
++#define MII_M1011_PHY_STATUS_100	0x4000
++#define MII_M1011_PHY_STATUS_SPD_MASK	0xc000
++#define MII_M1011_PHY_STATUS_FULLDUPLEX	0x2000
++#define MII_M1011_PHY_STATUS_RESOLVED	0x0800
++#define MII_M1011_PHY_STATUS_LINK	0x0400
++
+ 
+ MODULE_DESCRIPTION("Marvell PHY driver");
+ MODULE_AUTHOR("Andy Fleming");
+@@ -141,12 +157,22 @@ static int marvell_config_aneg(struct phy_device *phydev)
+ static int m88e1111_config_init(struct phy_device *phydev)
+ {
+ 	int err;
++	int temp;
++	int mode;
++
++	/* Enable Fiber/Copper auto selection */
++	temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
++	temp |= MII_M1111_HWCFG_FIBER_COPPER_AUTO;
++	phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
++
++	temp = phy_read(phydev, MII_BMCR);
++	temp |= BMCR_RESET;
++	phy_write(phydev, MII_BMCR, temp);
+ 
+ 	if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
+ 	    (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) ||
+ 	    (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
+ 	    (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
+-		int temp;
+ 
+ 		temp = phy_read(phydev, MII_M1111_PHY_EXT_CR);
+ 		if (temp < 0)
+@@ -171,7 +197,13 @@ static int m88e1111_config_init(struct phy_device *phydev)
+ 			return temp;
+ 
+ 		temp &= ~(MII_M1111_HWCFG_MODE_MASK);
+-		temp |= MII_M1111_HWCFG_MODE_RGMII;
++
++		mode = phy_read(phydev, MII_M1111_PHY_EXT_CR);
++
++		if (mode & MII_M1111_HWCFG_FIBER_COPPER_RES)
++			temp |= MII_M1111_HWCFG_MODE_FIBER_RGMII;
++		else
++			temp |= MII_M1111_HWCFG_MODE_COPPER_RGMII;
+ 
+ 		err = phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
+ 		if (err < 0)
+@@ -262,6 +294,93 @@ static int m88e1145_config_init(struct phy_device *phydev)
+ 	return 0;
+ }
+ 
++/* marvell_read_status
++ *
++ * Generic status code does not detect Fiber correctly!
++ * Description:
++ *   Check the link, then figure out the current state
++ *   by comparing what we advertise with what the link partner
++ *   advertises.  Start by checking the gigabit possibilities,
++ *   then move on to 10/100.
++ */
++static int marvell_read_status(struct phy_device *phydev)
++{
++	int adv;
++	int err;
++	int lpa;
++	int status = 0;
++
++	/* Update the link, but return if there
++	 * was an error */
++	err = genphy_update_link(phydev);
++	if (err)
++		return err;
++
++	if (AUTONEG_ENABLE == phydev->autoneg) {
++		status = phy_read(phydev, MII_M1011_PHY_STATUS);
++		if (status < 0)
++			return status;
++
++		lpa = phy_read(phydev, MII_LPA);
++		if (lpa < 0)
++			return lpa;
++
++		adv = phy_read(phydev, MII_ADVERTISE);
++		if (adv < 0)
++			return adv;
++
++		lpa &= adv;
++
++		if (status & MII_M1011_PHY_STATUS_FULLDUPLEX)
++			phydev->duplex = DUPLEX_FULL;
++		else
++			phydev->duplex = DUPLEX_HALF;
++
++		status = status & MII_M1011_PHY_STATUS_SPD_MASK;
++		phydev->pause = phydev->asym_pause = 0;
++
++		switch (status) {
++		case MII_M1011_PHY_STATUS_1000:
++			phydev->speed = SPEED_1000;
++			break;
++
++		case MII_M1011_PHY_STATUS_100:
++			phydev->speed = SPEED_100;
++			break;
++
++		default:
++			phydev->speed = SPEED_10;
++			break;
++		}
++
++		if (phydev->duplex == DUPLEX_FULL) {
++			phydev->pause = lpa & LPA_PAUSE_CAP ? 1 : 0;
++			phydev->asym_pause = lpa & LPA_PAUSE_ASYM ? 1 : 0;
++		}
++	} else {
++		int bmcr = phy_read(phydev, MII_BMCR);
++
++		if (bmcr < 0)
++			return bmcr;
++
++		if (bmcr & BMCR_FULLDPLX)
++			phydev->duplex = DUPLEX_FULL;
++		else
++			phydev->duplex = DUPLEX_HALF;
++
++		if (bmcr & BMCR_SPEED1000)
++			phydev->speed = SPEED_1000;
++		else if (bmcr & BMCR_SPEED100)
++			phydev->speed = SPEED_100;
++		else
++			phydev->speed = SPEED_10;
++
++		phydev->pause = phydev->asym_pause = 0;
++	}
++
++	return 0;
++}
++
+ static struct phy_driver marvell_drivers[] = {
+ 	{
+ 		.phy_id = 0x01410c60,
+@@ -296,7 +415,7 @@ static struct phy_driver marvell_drivers[] = {
+ 		.flags = PHY_HAS_INTERRUPT,
+ 		.config_init = &m88e1111_config_init,
+ 		.config_aneg = &marvell_config_aneg,
+-		.read_status = &genphy_read_status,
++		.read_status = &marvell_read_status,
+ 		.ack_interrupt = &marvell_ack_interrupt,
+ 		.config_intr = &marvell_config_intr,
+ 		.driver = { .owner = THIS_MODULE },
+diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
+index c72787a..3c915b8 100644
+--- a/drivers/net/s2io.c
++++ b/drivers/net/s2io.c
+@@ -4172,6 +4172,9 @@ static int s2io_xmit(struct sk_buff *skb, struct net_device *dev)
+ 	dev->trans_start = jiffies;
+ 	spin_unlock_irqrestore(&fifo->tx_lock, flags);
+ 
++	if (sp->config.intr_type == MSI_X)
++		tx_intr_handler(fifo);
++
+ 	return 0;
+ pci_map_failed:
+ 	stats->pci_map_fail_cnt++;
+diff --git a/drivers/net/skge.c b/drivers/net/skge.c
+index 186eb8e..2e26dce 100644
+--- a/drivers/net/skge.c
++++ b/drivers/net/skge.c
+@@ -3199,12 +3199,14 @@ static int skge_poll(struct napi_struct *napi, int to_do)
+ 	skge_write8(hw, Q_ADDR(rxqaddr[skge->port], Q_CSR), CSR_START);
+ 
+ 	if (work_done < to_do) {
+-		spin_lock_irq(&hw->hw_lock);
++		unsigned long flags;
++
++		spin_lock_irqsave(&hw->hw_lock, flags);
+ 		__netif_rx_complete(dev, napi);
+ 		hw->intr_mask |= napimask[skge->port];
+ 		skge_write32(hw, B0_IMSK, hw->intr_mask);
+ 		skge_read32(hw, B0_IMSK);
+-		spin_unlock_irq(&hw->hw_lock);
++		spin_unlock_irqrestore(&hw->hw_lock, flags);
+ 	}
+ 
+ 	return work_done;
+diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h
+index 51d4134..98a832a 100644
+--- a/drivers/net/smc91x.h
++++ b/drivers/net/smc91x.h
+@@ -92,14 +92,14 @@
+ #define SMC_insw(a, r, p, l) 	insw ((unsigned long *)((a) + (r)), p, l)
+ # endif
+ /* check if the mac in reg is valid */
+-#define SMC_GET_MAC_ADDR(addr)					\
++#define SMC_GET_MAC_ADDR(lp, addr)				\
+ 	do {							\
+ 		unsigned int __v;				\
+-		__v = SMC_inw(ioaddr, ADDR0_REG);		\
++		__v = SMC_inw(ioaddr, ADDR0_REG(lp));		\
+ 		addr[0] = __v; addr[1] = __v >> 8;		\
+-		__v = SMC_inw(ioaddr, ADDR1_REG);		\
++		__v = SMC_inw(ioaddr, ADDR1_REG(lp));		\
+ 		addr[2] = __v; addr[3] = __v >> 8;		\
+-		__v = SMC_inw(ioaddr, ADDR2_REG);		\
++		__v = SMC_inw(ioaddr, ADDR2_REG(lp));		\
+ 		addr[4] = __v; addr[5] = __v >> 8;		\
+ 		if (*(u32 *)(&addr[0]) == 0xFFFFFFFF) {		\
+ 			random_ether_addr(addr);		\
+diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c
+index 4b131a6..0343b00 100644
+--- a/drivers/net/usb/dm9601.c
++++ b/drivers/net/usb/dm9601.c
+@@ -341,7 +341,7 @@ static void dm9601_set_multicast(struct net_device *net)
+ 	/* We use the 20 byte dev->data for our 8 byte filter buffer
+ 	 * to avoid allocating memory that is tricky to free later */
+ 	u8 *hashes = (u8 *) & dev->data;
+-	u8 rx_ctl = 0x01;
++	u8 rx_ctl = 0x31;
+ 
+ 	memset(hashes, 0x00, DM_MCAST_SIZE);
+ 	hashes[DM_MCAST_SIZE - 1] |= 0x80;	/* broadcast address */
+@@ -562,6 +562,10 @@ static const struct usb_device_id products[] = {
+ 	 USB_DEVICE(0x0a46, 0x8515),	/* ADMtek ADM8515 USB NIC */
+ 	 .driver_info = (unsigned long)&dm9601_info,
+ 	 },
++	{
++	USB_DEVICE(0x0a47, 0x9601),	/* Hirose USB-100 */
++	.driver_info = (unsigned long)&dm9601_info,
++	 },
+ 	{},			// END
+ };
+ 
+diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c
+index 727547a..369c731 100644
+--- a/drivers/net/usb/rndis_host.c
++++ b/drivers/net/usb/rndis_host.c
+@@ -283,7 +283,7 @@ generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags)
+ 		struct rndis_set_c	*set_c;
+ 		struct rndis_halt	*halt;
+ 	} u;
+-	u32			tmp, *phym;
++	u32			tmp, phym_unspec, *phym;
+ 	int			reply_len;
+ 	unsigned char		*bp;
+ 
+@@ -363,12 +363,15 @@ generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags)
+ 		goto halt_fail_and_release;
+ 
+ 	/* Check physical medium */
++	phym = NULL;
+ 	reply_len = sizeof *phym;
+ 	retval = rndis_query(dev, intf, u.buf, OID_GEN_PHYSICAL_MEDIUM,
+ 			0, (void **) &phym, &reply_len);
+-	if (retval != 0)
++	if (retval != 0 || !phym) {
+ 		/* OID is optional so don't fail here. */
+-		*phym = RNDIS_PHYSICAL_MEDIUM_UNSPECIFIED;
++		phym_unspec = RNDIS_PHYSICAL_MEDIUM_UNSPECIFIED;
++		phym = &phym_unspec;
++	}
+ 	if ((flags & FLAG_RNDIS_PHYM_WIRELESS) &&
+ 			*phym != RNDIS_PHYSICAL_MEDIUM_WIRELESS_LAN) {
+ 		if (netif_msg_probe(dev))
+diff --git a/drivers/net/wireless/arlan-proc.c b/drivers/net/wireless/arlan-proc.c
+index c6e70db..2ab1d59 100644
+--- a/drivers/net/wireless/arlan-proc.c
++++ b/drivers/net/wireless/arlan-proc.c
+@@ -1202,13 +1202,6 @@ static ctl_table arlan_table[MAX_ARLANS + 1] =
+ 	{ .ctl_name = 0 }
+ };
+ #endif
+-#else
+-
+-static ctl_table arlan_table[MAX_ARLANS + 1] =
+-{
+-	{ .ctl_name = 0 }
+-};
+-#endif
+ 
+ 
+ // static int mmtu = 1234;
+@@ -1233,7 +1226,6 @@ static ctl_table arlan_root_table[] =
+ //};
+ 
+ 
+-#ifdef CONFIG_PROC_FS
+ static struct ctl_table_header *arlan_device_sysctl_header;
+ 
+ int __init init_arlan_proc(void)
+diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c
+index e38ed0f..7fca2eb 100644
+--- a/drivers/net/wireless/b43/debugfs.c
++++ b/drivers/net/wireless/b43/debugfs.c
+@@ -618,6 +618,7 @@ void b43_debugfs_remove_device(struct b43_wldev *dev)
+ 	kfree(e);
+ }
+ 
++/* Called with IRQs disabled. */
+ void b43_debugfs_log_txstat(struct b43_wldev *dev,
+ 			    const struct b43_txstatus *status)
+ {
+@@ -629,8 +630,7 @@ void b43_debugfs_log_txstat(struct b43_wldev *dev,
+ 	if (!e)
+ 		return;
+ 	log = &e->txstatlog;
+-	B43_WARN_ON(!irqs_disabled());
+-	spin_lock(&log->lock);
++	spin_lock(&log->lock); /* IRQs are already disabled. */
+ 	i = log->end + 1;
+ 	if (i == B43_NR_LOGGED_TXSTATUS)
+ 		i = 0;
+diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
+index 3dfb28a..cfbc1a2 100644
+--- a/drivers/net/wireless/b43/dma.c
++++ b/drivers/net/wireless/b43/dma.c
+@@ -560,7 +560,7 @@ static int b43_dmacontroller_tx_reset(struct b43_wldev *dev, u16 mmio_base,
+ /* Check if a DMA mapping address is invalid. */
+ static bool b43_dma_mapping_error(struct b43_dmaring *ring,
+ 				  dma_addr_t addr,
+-				  size_t buffersize)
++				  size_t buffersize, bool dma_to_device)
+ {
+ 	if (unlikely(dma_mapping_error(addr)))
+ 		return 1;
+@@ -568,11 +568,11 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring,
+ 	switch (ring->type) {
+ 	case B43_DMA_30BIT:
+ 		if ((u64)addr + buffersize > (1ULL << 30))
+-			return 1;
++			goto address_error;
+ 		break;
+ 	case B43_DMA_32BIT:
+ 		if ((u64)addr + buffersize > (1ULL << 32))
+-			return 1;
++			goto address_error;
+ 		break;
+ 	case B43_DMA_64BIT:
+ 		/* Currently we can't have addresses beyond
+@@ -582,6 +582,12 @@ static bool b43_dma_mapping_error(struct b43_dmaring *ring,
+ 
+ 	/* The address is OK. */
+ 	return 0;
++
++address_error:
++	/* We can't support this address. Unmap it again. */
++	unmap_descbuffer(ring, addr, buffersize, dma_to_device);
++
++	return 1;
+ }
+ 
+ static int setup_rx_descbuffer(struct b43_dmaring *ring,
+@@ -599,7 +605,7 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring,
+ 	if (unlikely(!skb))
+ 		return -ENOMEM;
+ 	dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0);
+-	if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize)) {
++	if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) {
+ 		/* ugh. try to realloc in zone_dma */
+ 		gfp_flags |= GFP_DMA;
+ 
+@@ -612,7 +618,7 @@ static int setup_rx_descbuffer(struct b43_dmaring *ring,
+ 					 ring->rx_buffersize, 0);
+ 	}
+ 
+-	if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize)) {
++	if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) {
+ 		dev_kfree_skb_any(skb);
+ 		return -EIO;
+ 	}
+@@ -852,7 +858,8 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
+ 					  b43_txhdr_size(dev),
+ 					  DMA_TO_DEVICE);
+ 
+-		if (b43_dma_mapping_error(ring, dma_test, b43_txhdr_size(dev))) {
++		if (b43_dma_mapping_error(ring, dma_test,
++					  b43_txhdr_size(dev), 1)) {
+ 			/* ugh realloc */
+ 			kfree(ring->txhdr_cache);
+ 			ring->txhdr_cache = kcalloc(nr_slots,
+@@ -867,7 +874,7 @@ struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev,
+ 						  DMA_TO_DEVICE);
+ 
+ 			if (b43_dma_mapping_error(ring, dma_test,
+-						  b43_txhdr_size(dev)))
++						  b43_txhdr_size(dev), 1))
+ 				goto err_kfree_txhdr_cache;
+ 		}
+ 
+@@ -1189,7 +1196,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
+ 
+ 	meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header,
+ 					   hdrsize, 1);
+-	if (b43_dma_mapping_error(ring, meta_hdr->dmaaddr, hdrsize)) {
++	if (b43_dma_mapping_error(ring, meta_hdr->dmaaddr, hdrsize, 1)) {
+ 		ring->current_slot = old_top_slot;
+ 		ring->used_slots = old_used_slots;
+ 		return -EIO;
+@@ -1208,7 +1215,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
+ 
+ 	meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
+ 	/* create a bounce buffer in zone_dma on mapping failure. */
+-	if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len)) {
++	if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
+ 		bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
+ 		if (!bounce_skb) {
+ 			ring->current_slot = old_top_slot;
+@@ -1222,7 +1229,7 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
+ 		skb = bounce_skb;
+ 		meta->skb = skb;
+ 		meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
+-		if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len)) {
++		if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
+ 			ring->current_slot = old_top_slot;
+ 			ring->used_slots = old_used_slots;
+ 			err = -EIO;
+@@ -1337,6 +1344,7 @@ out_unlock:
+ 	return err;
+ }
+ 
++/* Called with IRQs disabled. */
+ void b43_dma_handle_txstatus(struct b43_wldev *dev,
+ 			     const struct b43_txstatus *status)
+ {
+@@ -1349,8 +1357,8 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
+ 	ring = parse_cookie(dev, status->cookie, &slot);
+ 	if (unlikely(!ring))
+ 		return;
+-	B43_WARN_ON(!irqs_disabled());
+-	spin_lock(&ring->lock);
++
++	spin_lock(&ring->lock); /* IRQs are already disabled. */
+ 
+ 	B43_WARN_ON(!ring->tx);
+ 	ops = ring->ops;
+diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
+index 51dfce1..c73a75b 100644
+--- a/drivers/net/wireless/b43/main.c
++++ b/drivers/net/wireless/b43/main.c
+@@ -2049,7 +2049,6 @@ void b43_mac_enable(struct b43_wldev *dev)
+ {
+ 	dev->mac_suspended--;
+ 	B43_WARN_ON(dev->mac_suspended < 0);
+-	B43_WARN_ON(irqs_disabled());
+ 	if (dev->mac_suspended == 0) {
+ 		b43_write32(dev, B43_MMIO_MACCTL,
+ 			    b43_read32(dev, B43_MMIO_MACCTL)
+@@ -2075,7 +2074,6 @@ void b43_mac_suspend(struct b43_wldev *dev)
+ 	u32 tmp;
+ 
+ 	might_sleep();
+-	B43_WARN_ON(irqs_disabled());
+ 	B43_WARN_ON(dev->mac_suspended < 0);
+ 
+ 	if (dev->mac_suspended == 0) {
+diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
+index d1af938..b79a35a 100644
+--- a/drivers/net/wireless/iwlwifi/Kconfig
++++ b/drivers/net/wireless/iwlwifi/Kconfig
+@@ -20,7 +20,7 @@ config IWL4965
+ 	  runs.
+ 
+ 	  If you want to compile the driver as a module ( = code which can be
+-	  inserted in and remvoed from the running kernel whenever you want),
++	  inserted in and removed from the running kernel whenever you want),
+ 	  say M here and read <file:Documentation/kbuild/modules.txt>.  The
+ 	  module will be called iwl4965.ko.
+ 
+@@ -101,7 +101,7 @@ config IWL3945
+ 	  runs.
+ 
+ 	  If you want to compile the driver as a module ( = code which can be
+-	  inserted in and remvoed from the running kernel whenever you want),
++	  inserted in and removed from the running kernel whenever you want),
+ 	  say M here and read <file:Documentation/kbuild/modules.txt>.  The
+ 	  module will be called iwl3945.ko.
+ 
+diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
+index 40b71bc..cbaeaf1 100644
+--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
++++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
+@@ -6206,11 +6206,11 @@ static void iwl3945_alive_start(struct iwl3945_priv *priv)
+ 
+ 	/* At this point, the NIC is initialized and operational */
+ 	priv->notif_missed_beacons = 0;
+-	set_bit(STATUS_READY, &priv->status);
+ 
+ 	iwl3945_reg_txpower_periodic(priv);
+ 
+ 	IWL_DEBUG_INFO("ALIVE processing complete.\n");
++	set_bit(STATUS_READY, &priv->status);
+ 	wake_up_interruptible(&priv->wait_command_queue);
+ 
+ 	if (priv->error_recovering)
+@@ -8706,7 +8706,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
+ 	return err;
+ }
+ 
+-static void iwl3945_pci_remove(struct pci_dev *pdev)
++static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct iwl3945_priv *priv = pci_get_drvdata(pdev);
+ 	struct list_head *p, *q;
+diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
+index a23d479..60ec29e 100644
+--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
++++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
+@@ -6628,11 +6628,11 @@ static void iwl4965_alive_start(struct iwl4965_priv *priv)
+ 
+ 	/* At this point, the NIC is initialized and operational */
+ 	priv->notif_missed_beacons = 0;
+-	set_bit(STATUS_READY, &priv->status);
+ 
+ 	iwl4965_rf_kill_ct_config(priv);
+ 
+ 	IWL_DEBUG_INFO("ALIVE processing complete.\n");
++	set_bit(STATUS_READY, &priv->status);
+ 	wake_up_interruptible(&priv->wait_command_queue);
+ 
+ 	if (priv->error_recovering)
+@@ -9282,7 +9282,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
+ 	return err;
+ }
+ 
+-static void iwl4965_pci_remove(struct pci_dev *pdev)
++static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
+ {
+ 	struct iwl4965_priv *priv = pci_get_drvdata(pdev);
+ 	struct list_head *p, *q;
+diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
+index 8103d41..3909cf4 100644
+--- a/drivers/net/wireless/rt2x00/rt73usb.c
++++ b/drivers/net/wireless/rt2x00/rt73usb.c
+@@ -2095,6 +2095,8 @@ static struct usb_device_id rt73usb_device_table[] = {
+ 	{ USB_DEVICE(0x1371, 0x9032), USB_DEVICE_DATA(&rt73usb_ops) },
+ 	/* Conceptronic */
+ 	{ USB_DEVICE(0x14b2, 0x3c22), USB_DEVICE_DATA(&rt73usb_ops) },
++	/* Corega */
++	{ USB_DEVICE(0x07aa, 0x002e), USB_DEVICE_DATA(&rt73usb_ops) },
+ 	/* D-Link */
+ 	{ USB_DEVICE(0x07d1, 0x3c03), USB_DEVICE_DATA(&rt73usb_ops) },
+ 	{ USB_DEVICE(0x07d1, 0x3c04), USB_DEVICE_DATA(&rt73usb_ops) },
+diff --git a/drivers/net/wireless/wavelan_cs.h b/drivers/net/wireless/wavelan_cs.h
+index fabc63e..2e4bfe4 100644
+--- a/drivers/net/wireless/wavelan_cs.h
++++ b/drivers/net/wireless/wavelan_cs.h
+@@ -309,7 +309,7 @@ struct mmw_t
+ #define	MMW_EXT_ANT_INTERNAL	0x00	/* Internal antenna */
+ #define	MMW_EXT_ANT_EXTERNAL	0x03	/* External antenna */
+ #define	MMW_EXT_ANT_IQ_TEST	0x1C	/* IQ test pattern (set to 0) */
+-};
++} __attribute__((packed));
+ 
+ /* Size for structure checking (if padding is correct) */
+ #define	MMW_SIZE	37
+diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
+index 125e7b7..f7cb8e0 100644
+--- a/drivers/pci/setup-bus.c
++++ b/drivers/pci/setup-bus.c
+@@ -486,12 +486,7 @@ void __ref pci_bus_size_bridges(struct pci_bus *bus)
+ 		break;
+ 
+ 	case PCI_CLASS_BRIDGE_PCI:
+-		/* don't size subtractive decoding (transparent)
+-		 * PCI-to-PCI bridges */
+-		if (bus->self->transparent)
+-			break;
+ 		pci_bridge_check_ranges(bus);
+-		/* fall through */
+ 	default:
+ 		pbus_size_io(bus);
+ 		/* If the bridge supports prefetchable range, size it
+diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c
+index 6aa231e..2dcd196 100644
+--- a/drivers/pnp/pnpacpi/rsparser.c
++++ b/drivers/pnp/pnpacpi/rsparser.c
+@@ -85,7 +85,7 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_resource_table *res,
+ 	       i < PNP_MAX_IRQ)
+ 		i++;
+ 	if (i >= PNP_MAX_IRQ && !warned) {
+-		printk(KERN_ERR "pnpacpi: exceeded the max number of IRQ "
++		printk(KERN_WARNING "pnpacpi: exceeded the max number of IRQ "
+ 				"resources: %d \n", PNP_MAX_IRQ);
+ 		warned = 1;
+ 		return;
+@@ -187,7 +187,7 @@ static void pnpacpi_parse_allocated_dmaresource(struct pnp_resource_table *res,
+ 		res->dma_resource[i].start = dma;
+ 		res->dma_resource[i].end = dma;
+ 	} else if (!warned) {
+-		printk(KERN_ERR "pnpacpi: exceeded the max number of DMA "
++		printk(KERN_WARNING "pnpacpi: exceeded the max number of DMA "
+ 				"resources: %d \n", PNP_MAX_DMA);
+ 		warned = 1;
+ 	}
+@@ -213,7 +213,7 @@ static void pnpacpi_parse_allocated_ioresource(struct pnp_resource_table *res,
+ 		res->port_resource[i].start = io;
+ 		res->port_resource[i].end = io + len - 1;
+ 	} else if (!warned) {
+-		printk(KERN_ERR "pnpacpi: exceeded the max number of IO "
++		printk(KERN_WARNING "pnpacpi: exceeded the max number of IO "
+ 				"resources: %d \n", PNP_MAX_PORT);
+ 		warned = 1;
+ 	}
+@@ -241,7 +241,7 @@ static void pnpacpi_parse_allocated_memresource(struct pnp_resource_table *res,
+ 		res->mem_resource[i].start = mem;
+ 		res->mem_resource[i].end = mem + len - 1;
+ 	} else if (!warned) {
+-		printk(KERN_ERR "pnpacpi: exceeded the max number of mem "
++		printk(KERN_WARNING "pnpacpi: exceeded the max number of mem "
+ 				"resources: %d\n", PNP_MAX_MEM);
+ 		warned = 1;
+ 	}
+diff --git a/include/asm-avr32/byteorder.h b/include/asm-avr32/byteorder.h
+index 402ff41..d77b48b 100644
+--- a/include/asm-avr32/byteorder.h
++++ b/include/asm-avr32/byteorder.h
+@@ -12,8 +12,14 @@ extern unsigned long __builtin_bswap_32(unsigned long x);
+ extern unsigned short __builtin_bswap_16(unsigned short x);
+ #endif
+ 
++/*
++ * avr32-linux-gcc versions earlier than 4.2 improperly sign-extends
++ * the result.
++ */
++#if !(__GNUC__ == 4 && __GNUC_MINOR__ < 2)
+ #define __arch__swab32(x) __builtin_bswap_32(x)
+ #define __arch__swab16(x) __builtin_bswap_16(x)
++#endif
+ 
+ #if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+ # define __BYTEORDER_HAS_U64__
+diff --git a/include/asm-sparc64/cpudata.h b/include/asm-sparc64/cpudata.h
+index 5424214..532975e 100644
+--- a/include/asm-sparc64/cpudata.h
++++ b/include/asm-sparc64/cpudata.h
+@@ -86,6 +86,8 @@ extern struct trap_per_cpu trap_block[NR_CPUS];
+ extern void init_cur_cpu_trap(struct thread_info *);
+ extern void setup_tba(void);
+ extern int ncpus_probed;
++extern void __init cpu_probe(void);
++extern const struct seq_operations cpuinfo_op;
+ 
+ extern unsigned long real_hard_smp_processor_id(void);
+ 
+diff --git a/include/asm-sparc64/dcu.h b/include/asm-sparc64/dcu.h
+index ecbed2a..0f704e1 100644
+--- a/include/asm-sparc64/dcu.h
++++ b/include/asm-sparc64/dcu.h
+@@ -1,26 +1,27 @@
+-/* $Id: dcu.h,v 1.2 2001/03/01 23:23:33 davem Exp $ */
+ #ifndef _SPARC64_DCU_H
+ #define _SPARC64_DCU_H
+ 
++#include <linux/const.h>
++
+ /* UltraSparc-III Data Cache Unit Control Register */
+-#define DCU_CP		0x0002000000000000 /* Physical Cache Enable w/o mmu*/
+-#define DCU_CV		0x0001000000000000 /* Virtual Cache Enable	w/o mmu	*/
+-#define DCU_ME		0x0000800000000000 /* NC-store Merging Enable	*/
+-#define DCU_RE		0x0000400000000000 /* RAW bypass Enable		*/
+-#define DCU_PE		0x0000200000000000 /* PCache Enable		*/
+-#define DCU_HPE		0x0000100000000000 /* HW prefetch Enable		*/
+-#define DCU_SPE		0x0000080000000000 /* SW prefetch Enable		*/
+-#define DCU_SL		0x0000040000000000 /* Secondary load steering Enab	*/
+-#define DCU_WE		0x0000020000000000 /* WCache enable		*/
+-#define DCU_PM		0x000001fe00000000 /* PA Watchpoint Byte Mask	*/
+-#define DCU_VM		0x00000001fe000000 /* VA Watchpoint Byte Mask	*/
+-#define DCU_PR		0x0000000001000000 /* PA Watchpoint Read Enable	*/
+-#define DCU_PW		0x0000000000800000 /* PA Watchpoint Write Enable	*/
+-#define DCU_VR		0x0000000000400000 /* VA Watchpoint Read Enable	*/
+-#define DCU_VW		0x0000000000200000 /* VA Watchpoint Write Enable	*/
+-#define DCU_DM		0x0000000000000008 /* DMMU Enable			*/
+-#define DCU_IM		0x0000000000000004 /* IMMU Enable			*/
+-#define DCU_DC		0x0000000000000002 /* Data Cache Enable		*/
+-#define DCU_IC		0x0000000000000001 /* Instruction Cache Enable	*/
++#define DCU_CP	_AC(0x0002000000000000,UL) /* Phys Cache Enable w/o mmu	*/
++#define DCU_CV	_AC(0x0001000000000000,UL) /* Virt Cache Enable w/o mmu	*/
++#define DCU_ME	_AC(0x0000800000000000,UL) /* NC-store Merging Enable	*/
++#define DCU_RE	_AC(0x0000400000000000,UL) /* RAW bypass Enable		*/
++#define DCU_PE	_AC(0x0000200000000000,UL) /* PCache Enable		*/
++#define DCU_HPE	_AC(0x0000100000000000,UL) /* HW prefetch Enable	*/
++#define DCU_SPE	_AC(0x0000080000000000,UL) /* SW prefetch Enable	*/
++#define DCU_SL	_AC(0x0000040000000000,UL) /* Secondary ld-steering Enab*/
++#define DCU_WE	_AC(0x0000020000000000,UL) /* WCache enable		*/
++#define DCU_PM	_AC(0x000001fe00000000,UL) /* PA Watchpoint Byte Mask	*/
++#define DCU_VM	_AC(0x00000001fe000000,UL) /* VA Watchpoint Byte Mask	*/
++#define DCU_PR	_AC(0x0000000001000000,UL) /* PA Watchpoint Read Enable	*/
++#define DCU_PW	_AC(0x0000000000800000,UL) /* PA Watchpoint Write Enable*/
++#define DCU_VR	_AC(0x0000000000400000,UL) /* VA Watchpoint Read Enable	*/
++#define DCU_VW	_AC(0x0000000000200000,UL) /* VA Watchpoint Write Enable*/
++#define DCU_DM	_AC(0x0000000000000008,UL) /* DMMU Enable		*/
++#define DCU_IM	_AC(0x0000000000000004,UL) /* IMMU Enable		*/
++#define DCU_DC	_AC(0x0000000000000002,UL) /* Data Cache Enable		*/
++#define DCU_IC	_AC(0x0000000000000001,UL) /* Instruction Cache Enable	*/
+ 
+ #endif /* _SPARC64_DCU_H */
+diff --git a/include/asm-sparc64/irq.h b/include/asm-sparc64/irq.h
+index 30cb76b..0bb9bf5 100644
+--- a/include/asm-sparc64/irq.h
++++ b/include/asm-sparc64/irq.h
+@@ -64,6 +64,7 @@ extern unsigned char virt_irq_alloc(unsigned int dev_handle,
+ extern void virt_irq_free(unsigned int virt_irq);
+ #endif
+ 
++extern void __init init_IRQ(void);
+ extern void fixup_irqs(void);
+ 
+ static inline void set_softint(unsigned long bits)
+diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h
+index 3167ccf..549e452 100644
+--- a/include/asm-sparc64/pgtable.h
++++ b/include/asm-sparc64/pgtable.h
+@@ -23,9 +23,9 @@
+ #include <asm/page.h>
+ #include <asm/processor.h>
+ 
+-/* The kernel image occupies 0x4000000 to 0x1000000 (4MB --> 32MB).
+- * The page copy blockops can use 0x2000000 to 0x4000000.
+- * The TSB is mapped in the 0x4000000 to 0x6000000 range.
++/* The kernel image occupies 0x4000000 to 0x6000000 (4MB --> 96MB).
++ * The page copy blockops can use 0x6000000 to 0x8000000.
++ * The TSB is mapped in the 0x8000000 to 0xa000000 range.
+  * The PROM resides in an area spanning 0xf0000000 to 0x100000000.
+  * The vmalloc area spans 0x100000000 to 0x200000000.
+  * Since modules need to be in the lowest 32-bits of the address space,
+@@ -33,8 +33,8 @@
+  * There is a single static kernel PMD which maps from 0x0 to address
+  * 0x400000000.
+  */
+-#define	TLBTEMP_BASE		_AC(0x0000000002000000,UL)
+-#define	TSBMAP_BASE		_AC(0x0000000004000000,UL)
++#define	TLBTEMP_BASE		_AC(0x0000000006000000,UL)
++#define	TSBMAP_BASE		_AC(0x0000000008000000,UL)
+ #define MODULES_VADDR		_AC(0x0000000010000000,UL)
+ #define MODULES_LEN		_AC(0x00000000e0000000,UL)
+ #define MODULES_END		_AC(0x00000000f0000000,UL)
+@@ -761,6 +761,8 @@ extern unsigned long get_fb_unmapped_area(struct file *filp, unsigned long,
+ extern void pgtable_cache_init(void);
+ extern void sun4v_register_fault_status(void);
+ extern void sun4v_ktsb_register(void);
++extern void __init cheetah_ecache_flush_init(void);
++extern void sun4v_patch_tlb_handlers(void);
+ 
+ extern unsigned long cmdline_memory_size;
+ 
+diff --git a/include/asm-sparc64/processor.h b/include/asm-sparc64/processor.h
+index 8da484c..885b6a1 100644
+--- a/include/asm-sparc64/processor.h
++++ b/include/asm-sparc64/processor.h
+@@ -37,6 +37,9 @@
+ #endif
+ 
+ #define TASK_SIZE	((unsigned long)-VPTE_SIZE)
++#define TASK_SIZE_OF(tsk) \
++	(test_tsk_thread_flag(tsk,TIF_32BIT) ? \
++	 (1UL << 32UL) : TASK_SIZE)
+ #ifdef __KERNEL__
+ 
+ #define STACK_TOP32	((1UL << 32UL) - PAGE_SIZE)
+diff --git a/include/asm-sparc64/stacktrace.h b/include/asm-sparc64/stacktrace.h
+new file mode 100644
+index 0000000..6cee39a
+--- /dev/null
++++ b/include/asm-sparc64/stacktrace.h
+@@ -0,0 +1,6 @@
++#ifndef _SPARC64_STACKTRACE_H
++#define _SPARC64_STACKTRACE_H
++
++extern void stack_trace_flush(void);
++
++#endif /* _SPARC64_STACKTRACE_H */
+diff --git a/include/asm-sparc64/timer.h b/include/asm-sparc64/timer.h
+index ccbd694..5b779fd 100644
+--- a/include/asm-sparc64/timer.h
++++ b/include/asm-sparc64/timer.h
+@@ -1,14 +1,13 @@
+-/* $Id: timer.h,v 1.3 2000/05/09 17:40:15 davem Exp $
+- * timer.h: System timer definitions for sun5.
++/* timer.h: System timer definitions for sun5.
+  *
+- * Copyright (C) 1997 David S. Miller (davem at caip.rutgers.edu)
++ * Copyright (C) 1997, 2008 David S. Miller (davem at davemloft.net)
+  */
+ 
+ #ifndef _SPARC64_TIMER_H
+ #define _SPARC64_TIMER_H
+ 
+ #include <linux/types.h>
+-
++#include <linux/init.h>
+ 
+ struct sparc64_tick_ops {
+ 	unsigned long (*get_tick)(void);
+@@ -25,5 +24,7 @@ struct sparc64_tick_ops {
+ extern struct sparc64_tick_ops *tick_ops;
+ 
+ extern unsigned long sparc64_get_clock_tick(unsigned int cpu);
++extern void __devinit setup_sparc64_timer(void);
++extern void __init time_init(void);
+ 
+ #endif /* _SPARC64_TIMER_H */
+diff --git a/include/asm-x86/mach-rdc321x/gpio.h b/include/asm-x86/mach-rdc321x/gpio.h
+index db31b92..acce0b7 100644
+--- a/include/asm-x86/mach-rdc321x/gpio.h
++++ b/include/asm-x86/mach-rdc321x/gpio.h
+@@ -5,19 +5,20 @@ extern int rdc_gpio_get_value(unsigned gpio);
+ extern void rdc_gpio_set_value(unsigned gpio, int value);
+ extern int rdc_gpio_direction_input(unsigned gpio);
+ extern int rdc_gpio_direction_output(unsigned gpio, int value);
+-
++extern int rdc_gpio_request(unsigned gpio, const char *label);
++extern void rdc_gpio_free(unsigned gpio);
++extern void __init rdc321x_gpio_setup(void);
+ 
+ /* Wrappers for the arch-neutral GPIO API */
+ 
+ static inline int gpio_request(unsigned gpio, const char *label)
+ {
+-	/* Not yet implemented */
+-	return 0;
++	return rdc_gpio_request(gpio, label);
+ }
+ 
+ static inline void gpio_free(unsigned gpio)
+ {
+-	/* Not yet implemented */
++	rdc_gpio_free(gpio);
+ }
+ 
+ static inline int gpio_direction_input(unsigned gpio)
+diff --git a/include/asm-x86/mach-rdc321x/rdc321x_defs.h b/include/asm-x86/mach-rdc321x/rdc321x_defs.h
+index 838ba8f..c8e9c8b 100644
+--- a/include/asm-x86/mach-rdc321x/rdc321x_defs.h
++++ b/include/asm-x86/mach-rdc321x/rdc321x_defs.h
+@@ -3,4 +3,10 @@
+ /* General purpose configuration and data registers */
+ #define RDC3210_CFGREG_ADDR     0x0CF8
+ #define RDC3210_CFGREG_DATA     0x0CFC
+-#define RDC_MAX_GPIO		0x3A
++
++#define RDC321X_GPIO_CTRL_REG1	0x48
++#define RDC321X_GPIO_CTRL_REG2	0x84
++#define RDC321X_GPIO_DATA_REG1	0x4c
++#define RDC321X_GPIO_DATA_REG2	0x88
++
++#define RDC321X_MAX_GPIO	58
+diff --git a/include/asm-x86/pgtable.h b/include/asm-x86/pgtable.h
+index 174b877..9cf472a 100644
+--- a/include/asm-x86/pgtable.h
++++ b/include/asm-x86/pgtable.h
+@@ -85,6 +85,7 @@ extern pteval_t __PAGE_KERNEL, __PAGE_KERNEL_EXEC;
+ #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)
+@@ -101,6 +102,7 @@ extern pteval_t __PAGE_KERNEL, __PAGE_KERNEL_EXEC;
+ #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)
+diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
+index 6b72a45..51e6b1e 100644
+--- a/include/linux/cpuidle.h
++++ b/include/linux/cpuidle.h
+@@ -38,8 +38,8 @@ struct cpuidle_state {
+ 	unsigned int	power_usage; /* in mW */
+ 	unsigned int	target_residency; /* in US */
+ 
+-	unsigned int	usage;
+-	unsigned int	time; /* in US */
++	unsigned long long	usage;
++	unsigned long long	time; /* in US */
+ 
+ 	int (*enter)	(struct cpuidle_device *dev,
+ 			 struct cpuidle_state *state);
+diff --git a/include/linux/sched.h b/include/linux/sched.h
+index fed07d0..6a1e7af 100644
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -1541,6 +1541,12 @@ static inline void idle_task_exit(void) {}
+ 
+ extern void sched_idle_next(void);
+ 
++#if defined(CONFIG_NO_HZ) && defined(CONFIG_SMP)
++extern void wake_up_idle_cpu(int cpu);
++#else
++static inline void wake_up_idle_cpu(int cpu) { }
++#endif
++
+ #ifdef CONFIG_SCHED_DEBUG
+ extern unsigned int sysctl_sched_latency;
+ extern unsigned int sysctl_sched_min_granularity;
+diff --git a/include/net/neighbour.h b/include/net/neighbour.h
+index ebbfb50..64a5f01 100644
+--- a/include/net/neighbour.h
++++ b/include/net/neighbour.h
+@@ -218,6 +218,10 @@ extern unsigned long		neigh_rand_reach_time(unsigned long base);
+ extern void			pneigh_enqueue(struct neigh_table *tbl, struct neigh_parms *p,
+ 					       struct sk_buff *skb);
+ extern struct pneigh_entry	*pneigh_lookup(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev, int creat);
++extern struct pneigh_entry	*__pneigh_lookup(struct neigh_table *tbl,
++						 struct net *net,
++						 const void *key,
++						 struct net_device *dev);
+ extern int			pneigh_delete(struct neigh_table *tbl, struct net *net, const void *key, struct net_device *dev);
+ 
+ extern void neigh_app_ns(struct neighbour *n);
+diff --git a/include/net/xfrm.h b/include/net/xfrm.h
+index 619c53b..0d255ae 100644
+--- a/include/net/xfrm.h
++++ b/include/net/xfrm.h
+@@ -204,6 +204,7 @@ struct xfrm_state
+ 	 * transformer. */
+ 	const struct xfrm_type	*type;
+ 	struct xfrm_mode	*inner_mode;
++	struct xfrm_mode	*inner_mode_iaf;
+ 	struct xfrm_mode	*outer_mode;
+ 
+ 	/* Security context */
+@@ -387,6 +388,27 @@ enum {
+ extern int xfrm_register_mode(struct xfrm_mode *mode, int family);
+ extern int xfrm_unregister_mode(struct xfrm_mode *mode, int family);
+ 
++static inline int xfrm_af2proto(unsigned int family)
++{
++	switch(family) {
++	case AF_INET:
++		return IPPROTO_IPIP;
++	case AF_INET6:
++		return IPPROTO_IPV6;
++	default:
++		return 0;
++	}
++}
++
++static inline struct xfrm_mode *xfrm_ip2inner_mode(struct xfrm_state *x, int ipproto)
++{
++	if ((ipproto == IPPROTO_IPIP && x->props.family == AF_INET) ||
++	    (ipproto == IPPROTO_IPV6 && x->props.family == AF_INET6))
++		return x->inner_mode;
++	else
++		return x->inner_mode_iaf;
++}
++
+ struct xfrm_tmpl
+ {
+ /* id in template is interpreted as:
+@@ -530,6 +552,9 @@ struct xfrm_mode_skb_cb {
+ 	__be16 id;
+ 	__be16 frag_off;
+ 
++	/* IP header length (excluding options or extension headers). */
++	u8 ihl;
++
+ 	/* TOS for IPv4, class for IPv6. */
+ 	u8 tos;
+ 
+@@ -539,6 +564,9 @@ struct xfrm_mode_skb_cb {
+ 	/* Protocol for IPv4, NH for IPv6. */
+ 	u8 protocol;
+ 
++	/* Option length for IPv4, zero for IPv6. */
++	u8 optlen;
++
+ 	/* Used by IPv6 only, zero for IPv4. */
+ 	u8 flow_lbl[3];
+ };
+@@ -1253,6 +1281,7 @@ extern int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi,
+ extern int xfrm_input_resume(struct sk_buff *skb, int nexthdr);
+ extern int xfrm_output_resume(struct sk_buff *skb, int err);
+ extern int xfrm_output(struct sk_buff *skb);
++extern int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb);
+ extern int xfrm4_extract_header(struct sk_buff *skb);
+ extern int xfrm4_extract_input(struct xfrm_state *x, struct sk_buff *skb);
+ extern int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
+diff --git a/kernel/futex.c b/kernel/futex.c
+index 06968cd..87a6428 100644
+--- a/kernel/futex.c
++++ b/kernel/futex.c
+@@ -2158,7 +2158,7 @@ static struct file_system_type futex_fs_type = {
+ 	.kill_sb	= kill_anon_super,
+ };
+ 
+-static int __init init(void)
++static int __init futex_init(void)
+ {
+ 	u32 curval;
+ 	int i;
+@@ -2194,4 +2194,4 @@ static int __init init(void)
+ 
+ 	return 0;
+ }
+-__initcall(init);
++__initcall(futex_init);
+diff --git a/kernel/relay.c b/kernel/relay.c
+index 4c035a8..d6204a4 100644
+--- a/kernel/relay.c
++++ b/kernel/relay.c
+@@ -736,7 +736,7 @@ static int relay_file_open(struct inode *inode, struct file *filp)
+ 	kref_get(&buf->kref);
+ 	filp->private_data = buf;
+ 
+-	return 0;
++	return nonseekable_open(inode, filp);
+ }
+ 
+ /**
+@@ -1056,6 +1056,10 @@ static struct pipe_buf_operations relay_pipe_buf_ops = {
+ 	.get = generic_pipe_buf_get,
+ };
+ 
++static void relay_page_release(struct splice_pipe_desc *spd, unsigned int i)
++{
++}
++
+ /*
+  *	subbuf_splice_actor - splice up to one subbuf's worth of data
+  */
+@@ -1083,6 +1087,7 @@ static int subbuf_splice_actor(struct file *in,
+ 		.partial = partial,
+ 		.flags = flags,
+ 		.ops = &relay_pipe_buf_ops,
++		.spd_release = relay_page_release,
+ 	};
+ 
+ 	if (rbuf->subbufs_produced == rbuf->subbufs_consumed)
+diff --git a/kernel/sched.c b/kernel/sched.c
+index 28c73f0..8dcdec6 100644
+--- a/kernel/sched.c
++++ b/kernel/sched.c
+@@ -1052,6 +1052,49 @@ static void resched_cpu(int cpu)
+ 	resched_task(cpu_curr(cpu));
+ 	spin_unlock_irqrestore(&rq->lock, flags);
+ }
++
++#ifdef CONFIG_NO_HZ
++/*
++ * When add_timer_on() enqueues a timer into the timer wheel of an
++ * idle CPU then this timer might expire before the next timer event
++ * which is scheduled to wake up that CPU. In case of a completely
++ * idle system the next event might even be infinite time into the
++ * future. wake_up_idle_cpu() ensures that the CPU is woken up and
++ * leaves the inner idle loop so the newly added timer is taken into
++ * account when the CPU goes back to idle and evaluates the timer
++ * wheel for the next timer event.
++ */
++void wake_up_idle_cpu(int cpu)
++{
++	struct rq *rq = cpu_rq(cpu);
++
++	if (cpu == smp_processor_id())
++		return;
++
++	/*
++	 * This is safe, as this function is called with the timer
++	 * wheel base lock of (cpu) held. When the CPU is on the way
++	 * to idle and has not yet set rq->curr to idle then it will
++	 * be serialized on the timer wheel base lock and take the new
++	 * timer into account automatically.
++	 */
++	if (rq->curr != rq->idle)
++		return;
++
++	/*
++	 * We can set TIF_RESCHED on the idle task of the other CPU
++	 * lockless. The worst case is that the other CPU runs the
++	 * idle task through an additional NOOP schedule()
++	 */
++	set_tsk_thread_flag(rq->idle, TIF_NEED_RESCHED);
++
++	/* NEED_RESCHED must be visible before we test polling */
++	smp_mb();
++	if (!tsk_is_polling(rq->idle))
++		smp_send_reschedule(cpu);
++}
++#endif
++
+ #else
+ static void __resched_task(struct task_struct *p, int tif_bit)
+ {
+diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
+index 278534b..7f60097 100644
+--- a/kernel/time/clocksource.c
++++ b/kernel/time/clocksource.c
+@@ -174,7 +174,7 @@ static void clocksource_check_watchdog(struct clocksource *cs)
+ 			if (watchdog)
+ 				del_timer(&watchdog_timer);
+ 			watchdog = cs;
+-			init_timer_deferrable(&watchdog_timer);
++			init_timer(&watchdog_timer);
+ 			watchdog_timer.function = clocksource_watchdog;
+ 
+ 			/* Reset watchdog cycles */
+diff --git a/kernel/timer.c b/kernel/timer.c
+index 99b00a2..b024106 100644
+--- a/kernel/timer.c
++++ b/kernel/timer.c
+@@ -451,10 +451,18 @@ void add_timer_on(struct timer_list *timer, int cpu)
+ 	spin_lock_irqsave(&base->lock, flags);
+ 	timer_set_base(timer, base);
+ 	internal_add_timer(base, timer);
++	/*
++	 * Check whether the other CPU is idle and needs to be
++	 * triggered to reevaluate the timer wheel when nohz is
++	 * active. We are protected against the other CPU fiddling
++	 * with the timer by holding the timer base lock. This also
++	 * makes sure that a CPU on the way to idle can not evaluate
++	 * the timer wheel.
++	 */
++	wake_up_idle_cpu(cpu);
+ 	spin_unlock_irqrestore(&base->lock, flags);
+ }
+ 
+-
+ /**
+  * mod_timer - modify a timer's timeout
+  * @timer: the timer to be modified
+diff --git a/mm/hugetlb.c b/mm/hugetlb.c
+index 74c1b6b..51c9e2c 100644
+--- a/mm/hugetlb.c
++++ b/mm/hugetlb.c
+@@ -401,12 +401,20 @@ static void return_unused_surplus_pages(unsigned long unused_resv_pages)
+ 	struct page *page;
+ 	unsigned long nr_pages;
+ 
++	/*
++	 * We want to release as many surplus pages as possible, spread
++	 * evenly across all nodes. Iterate across all nodes until we
++	 * can no longer free unreserved surplus pages. This occurs when
++	 * the nodes with surplus pages have no free pages.
++	 */
++	unsigned long remaining_iterations = num_online_nodes();
++
+ 	/* Uncommit the reservation */
+ 	resv_huge_pages -= unused_resv_pages;
+ 
+ 	nr_pages = min(unused_resv_pages, surplus_huge_pages);
+ 
+-	while (nr_pages) {
++	while (remaining_iterations-- && nr_pages) {
+ 		nid = next_node(nid, node_online_map);
+ 		if (nid == MAX_NUMNODES)
+ 			nid = first_node(node_online_map);
+@@ -424,6 +432,7 @@ static void return_unused_surplus_pages(unsigned long unused_resv_pages)
+ 			surplus_huge_pages--;
+ 			surplus_huge_pages_node[nid]--;
+ 			nr_pages--;
++			remaining_iterations = num_online_nodes();
+ 		}
+ 	}
+ }
+@@ -671,9 +680,11 @@ int hugetlb_report_node_meminfo(int nid, char *buf)
+ {
+ 	return sprintf(buf,
+ 		"Node %d HugePages_Total: %5u\n"
+-		"Node %d HugePages_Free:  %5u\n",
++		"Node %d HugePages_Free:  %5u\n"
++		"Node %d HugePages_Surp:  %5u\n",
+ 		nid, nr_huge_pages_node[nid],
+-		nid, free_huge_pages_node[nid]);
++		nid, free_huge_pages_node[nid],
++		nid, surplus_huge_pages_node[nid]);
+ }
+ 
+ /* Return the number pages of memory we physically have, in PAGE_SIZE units. */
+diff --git a/mm/slab.c b/mm/slab.c
+index bb4070e..04b308c 100644
+--- a/mm/slab.c
++++ b/mm/slab.c
+@@ -1481,7 +1481,7 @@ void __init kmem_cache_init(void)
+ 	list_add(&cache_cache.next, &cache_chain);
+ 	cache_cache.colour_off = cache_line_size();
+ 	cache_cache.array[smp_processor_id()] = &initarray_cache.cache;
+-	cache_cache.nodelists[node] = &initkmem_list3[CACHE_CACHE];
++	cache_cache.nodelists[node] = &initkmem_list3[CACHE_CACHE + node];
+ 
+ 	/*
+ 	 * struct kmem_cache size depends on nr_node_ids, which
+@@ -1602,7 +1602,7 @@ void __init kmem_cache_init(void)
+ 		int nid;
+ 
+ 		for_each_online_node(nid) {
+-			init_list(&cache_cache, &initkmem_list3[CACHE_CACHE], nid);
++			init_list(&cache_cache, &initkmem_list3[CACHE_CACHE + nid], nid);
+ 
+ 			init_list(malloc_sizes[INDEX_AC].cs_cachep,
+ 				  &initkmem_list3[SIZE_AC + nid], nid);
+diff --git a/mm/slub.c b/mm/slub.c
+index ca71d5b..b72bc98 100644
+--- a/mm/slub.c
++++ b/mm/slub.c
+@@ -2685,6 +2685,7 @@ void kfree(const void *x)
+ }
+ EXPORT_SYMBOL(kfree);
+ 
++#if defined(SLUB_DEBUG) || defined(CONFIG_SLABINFO)
+ static unsigned long count_partial(struct kmem_cache_node *n)
+ {
+ 	unsigned long flags;
+@@ -2697,6 +2698,7 @@ static unsigned long count_partial(struct kmem_cache_node *n)
+ 	spin_unlock_irqrestore(&n->list_lock, flags);
+ 	return x;
+ }
++#endif
+ 
+ /*
+  * kmem_cache_shrink removes empty slabs from the partial lists and sorts
+diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
+index 8fbcefe..480ea90 100644
+--- a/net/8021q/vlan_dev.c
++++ b/net/8021q/vlan_dev.c
+@@ -660,7 +660,7 @@ static int vlan_dev_init(struct net_device *dev)
+ 	int subclass = 0;
+ 
+ 	/* IFF_BROADCAST|IFF_MULTICAST; ??? */
+-	dev->flags  = real_dev->flags & ~IFF_UP;
++	dev->flags  = real_dev->flags & ~(IFF_UP | IFF_PROMISC | IFF_ALLMULTI);
+ 	dev->iflink = real_dev->ifindex;
+ 	dev->state  = (real_dev->state & ((1<<__LINK_STATE_NOCARRIER) |
+ 					  (1<<__LINK_STATE_DORMANT))) |
+diff --git a/net/ax25/TODO b/net/ax25/TODO
+index 4089c49..69fb4e3 100644
+--- a/net/ax25/TODO
++++ b/net/ax25/TODO
+@@ -9,10 +9,6 @@ being used.
+ Routes to a device being taken down might be deleted by ax25_rt_device_down
+ but added by somebody else before the device has been deleted fully.
+ 
+-Massive amounts of lock_kernel / unlock_kernel are just a temporary solution to
+-get around the removal of SOCKOPS_WRAP.  A serious locking strategy has to be
+-implemented.
+-
+ The ax25_rt_find_route synopsys is pervert but I somehow had to deal with
+ the race caused by the static variable in it's previous implementation.
+ 
+diff --git a/net/core/dev.c b/net/core/dev.c
+index fcdf03c..460e7f9 100644
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -3329,7 +3329,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
+ 			return -EOPNOTSUPP;
+ 
+ 		case SIOCADDMULTI:
+-			if (!dev->set_multicast_list ||
++			if ((!dev->set_multicast_list && !dev->set_rx_mode) ||
+ 			    ifr->ifr_hwaddr.sa_family != AF_UNSPEC)
+ 				return -EINVAL;
+ 			if (!netif_device_present(dev))
+@@ -3338,7 +3338,7 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
+ 					  dev->addr_len, 1);
+ 
+ 		case SIOCDELMULTI:
+-			if (!dev->set_multicast_list ||
++			if ((!dev->set_multicast_list && !dev->set_rx_mode) ||
+ 			    ifr->ifr_hwaddr.sa_family != AF_UNSPEC)
+ 				return -EINVAL;
+ 			if (!netif_device_present(dev))
+diff --git a/net/core/neighbour.c b/net/core/neighbour.c
+index d9a02b2..19b8e00 100644
+--- a/net/core/neighbour.c
++++ b/net/core/neighbour.c
+@@ -466,6 +466,28 @@ out_neigh_release:
+ 	goto out;
+ }
+ 
++struct pneigh_entry *__pneigh_lookup(struct neigh_table *tbl,
++		struct net *net, const void *pkey, struct net_device *dev)
++{
++	struct pneigh_entry *n;
++	int key_len = tbl->key_len;
++	u32 hash_val = *(u32 *)(pkey + key_len - 4);
++
++	hash_val ^= (hash_val >> 16);
++	hash_val ^= hash_val >> 8;
++	hash_val ^= hash_val >> 4;
++	hash_val &= PNEIGH_HASHMASK;
++
++	for (n = tbl->phash_buckets[hash_val]; n; n = n->next) {
++		if (!memcmp(n->key, pkey, key_len) &&
++		    (n->net == net) &&
++		    (n->dev == dev || !n->dev))
++			break;
++	}
++
++	return n;
++}
++
+ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
+ 				    struct net *net, const void *pkey,
+ 				    struct net_device *dev, int creat)
+@@ -2803,6 +2825,7 @@ EXPORT_SYMBOL(neigh_table_init_no_netlink);
+ EXPORT_SYMBOL(neigh_update);
+ EXPORT_SYMBOL(pneigh_enqueue);
+ EXPORT_SYMBOL(pneigh_lookup);
++EXPORT_SYMBOL_GPL(__pneigh_lookup);
+ 
+ #ifdef CONFIG_ARPD
+ EXPORT_SYMBOL(neigh_app_ns);
+diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
+index a13c074..a944e80 100644
+--- a/net/ipv4/icmp.c
++++ b/net/ipv4/icmp.c
+@@ -591,7 +591,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
+ 		}
+ 
+ 		if (xfrm_decode_session_reverse(skb_in, &fl, AF_INET))
+-			goto out_unlock;
++			goto ende;
+ 
+ 		if (inet_addr_type(net, fl.fl4_src) == RTN_LOCAL)
+ 			err = __ip_route_output_key(net, &rt2, &fl);
+@@ -601,7 +601,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
+ 
+ 			fl2.fl4_dst = fl.fl4_src;
+ 			if (ip_route_output_key(net, &rt2, &fl2))
+-				goto out_unlock;
++				goto ende;
+ 
+ 			/* Ugh! */
+ 			odst = skb_in->dst;
+@@ -614,7 +614,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
+ 		}
+ 
+ 		if (err)
+-			goto out_unlock;
++			goto ende;
+ 
+ 		err = xfrm_lookup((struct dst_entry **)&rt2, &fl, NULL,
+ 				  XFRM_LOOKUP_ICMP);
+diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
+index b47030b..9c798ab 100644
+--- a/net/ipv4/xfrm4_mode_beet.c
++++ b/net/ipv4/xfrm4_mode_beet.c
+@@ -39,13 +39,11 @@ static void xfrm4_beet_make_header(struct sk_buff *skb)
+ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
+ {
+ 	struct ip_beet_phdr *ph;
+-	struct iphdr *iph, *top_iph;
++	struct iphdr *top_iph;
+ 	int hdrlen, optlen;
+ 
+-	iph = ip_hdr(skb);
+-
+ 	hdrlen = 0;
+-	optlen = iph->ihl * 4 - sizeof(*iph);
++	optlen = XFRM_MODE_SKB_CB(skb)->optlen;
+ 	if (unlikely(optlen))
+ 		hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4);
+ 
+@@ -53,11 +51,12 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
+ 				    hdrlen);
+ 	skb->mac_header = skb->network_header +
+ 			  offsetof(struct iphdr, protocol);
+-	skb->transport_header = skb->network_header + sizeof(*iph);
++	skb->transport_header = skb->network_header + sizeof(*top_iph);
+ 
+ 	xfrm4_beet_make_header(skb);
+ 
+-	ph = (struct ip_beet_phdr *)__skb_pull(skb, sizeof(*iph) - hdrlen);
++	ph = (struct ip_beet_phdr *)
++		__skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl - hdrlen);
+ 
+ 	top_iph = ip_hdr(skb);
+ 
+diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
+index 8dee617..584e6d7 100644
+--- a/net/ipv4/xfrm4_mode_tunnel.c
++++ b/net/ipv4/xfrm4_mode_tunnel.c
+@@ -41,7 +41,7 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
+ 	top_iph->ihl = 5;
+ 	top_iph->version = 4;
+ 
+-	top_iph->protocol = x->inner_mode->afinfo->proto;
++	top_iph->protocol = xfrm_af2proto(skb->dst->ops->family);
+ 
+ 	/* DS disclosed */
+ 	top_iph->tos = INET_ECN_encapsulate(XFRM_MODE_SKB_CB(skb)->tos,
+diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
+index d5a58a8..8c3180a 100644
+--- a/net/ipv4/xfrm4_output.c
++++ b/net/ipv4/xfrm4_output.c
+@@ -56,7 +56,7 @@ int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
+ {
+ 	int err;
+ 
+-	err = x->inner_mode->afinfo->extract_output(x, skb);
++	err = xfrm_inner_extract_output(x, skb);
+ 	if (err)
+ 		return err;
+ 
+diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
+index fdeebe6..07735ed 100644
+--- a/net/ipv4/xfrm4_state.c
++++ b/net/ipv4/xfrm4_state.c
+@@ -52,10 +52,12 @@ int xfrm4_extract_header(struct sk_buff *skb)
+ {
+ 	struct iphdr *iph = ip_hdr(skb);
+ 
++	XFRM_MODE_SKB_CB(skb)->ihl = sizeof(*iph);
+ 	XFRM_MODE_SKB_CB(skb)->id = iph->id;
+ 	XFRM_MODE_SKB_CB(skb)->frag_off = iph->frag_off;
+ 	XFRM_MODE_SKB_CB(skb)->tos = iph->tos;
+ 	XFRM_MODE_SKB_CB(skb)->ttl = iph->ttl;
++	XFRM_MODE_SKB_CB(skb)->optlen = iph->ihl * 4 - sizeof(*iph);
+ 	memset(XFRM_MODE_SKB_CB(skb)->flow_lbl, 0,
+ 	       sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl));
+ 
+diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
+index 51557c2..452a2ac 100644
+--- a/net/ipv6/ndisc.c
++++ b/net/ipv6/ndisc.c
+@@ -676,6 +676,20 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb)
+ 	}
+ }
+ 
++static struct pneigh_entry *pndisc_check_router(struct net_device *dev,
++		struct in6_addr *addr, int *is_router)
++{
++	struct pneigh_entry *n;
++
++	read_lock_bh(&nd_tbl.lock);
++	n = __pneigh_lookup(&nd_tbl, &init_net, addr, dev);
++	if (n != NULL)
++		*is_router = (n->flags & NTF_ROUTER);
++	read_unlock_bh(&nd_tbl.lock);
++
++	return n;
++}
++
+ static void ndisc_recv_ns(struct sk_buff *skb)
+ {
+ 	struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb);
+@@ -692,7 +706,7 @@ static void ndisc_recv_ns(struct sk_buff *skb)
+ 	struct pneigh_entry *pneigh = NULL;
+ 	int dad = ipv6_addr_any(saddr);
+ 	int inc;
+-	int is_router;
++	int is_router = 0;
+ 
+ 	if (ipv6_addr_is_multicast(&msg->target)) {
+ 		ND_PRINTK2(KERN_WARNING
+@@ -790,8 +804,8 @@ static void ndisc_recv_ns(struct sk_buff *skb)
+ 		if (ipv6_chk_acast_addr(dev, &msg->target) ||
+ 		    (idev->cnf.forwarding &&
+ 		     (ipv6_devconf.proxy_ndp || idev->cnf.proxy_ndp) &&
+-		     (pneigh = pneigh_lookup(&nd_tbl, &init_net,
+-					     &msg->target, dev, 0)) != NULL)) {
++		     (pneigh = pndisc_check_router(dev, &msg->target,
++						  &is_router)) != NULL)) {
+ 			if (!(NEIGH_CB(skb)->flags & LOCALLY_ENQUEUED) &&
+ 			    skb->pkt_type != PACKET_HOST &&
+ 			    inc != 0 &&
+@@ -812,7 +826,7 @@ static void ndisc_recv_ns(struct sk_buff *skb)
+ 			goto out;
+ 	}
+ 
+-	is_router = !!(pneigh ? pneigh->flags & NTF_ROUTER : idev->cnf.forwarding);
++	is_router = !!(pneigh ? is_router : idev->cnf.forwarding);
+ 
+ 	if (dad) {
+ 		struct in6_addr maddr;
+diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c
+index 0527d11..d6ce400 100644
+--- a/net/ipv6/xfrm6_mode_beet.c
++++ b/net/ipv6/xfrm6_mode_beet.c
+@@ -45,6 +45,7 @@ static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb)
+ 	skb->mac_header = skb->network_header +
+ 			  offsetof(struct ipv6hdr, nexthdr);
+ 	skb->transport_header = skb->network_header + sizeof(*top_iph);
++	__skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl);
+ 
+ 	xfrm6_beet_make_header(skb);
+ 
+diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
+index 0c742fa..e20529b 100644
+--- a/net/ipv6/xfrm6_mode_tunnel.c
++++ b/net/ipv6/xfrm6_mode_tunnel.c
+@@ -45,7 +45,7 @@ static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
+ 
+ 	memcpy(top_iph->flow_lbl, XFRM_MODE_SKB_CB(skb)->flow_lbl,
+ 	       sizeof(top_iph->flow_lbl));
+-	top_iph->nexthdr = x->inner_mode->afinfo->proto;
++	top_iph->nexthdr = xfrm_af2proto(skb->dst->ops->family);
+ 
+ 	dsfield = XFRM_MODE_SKB_CB(skb)->tos;
+ 	dsfield = INET_ECN_encapsulate(dsfield, dsfield);
+diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
+index 79ccfb0..0af823c 100644
+--- a/net/ipv6/xfrm6_output.c
++++ b/net/ipv6/xfrm6_output.c
+@@ -62,7 +62,7 @@ int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
+ {
+ 	int err;
+ 
+-	err = x->inner_mode->afinfo->extract_output(x, skb);
++	err = xfrm_inner_extract_output(x, skb);
+ 	if (err)
+ 		return err;
+ 
+diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
+index dc817e0..ff1e1db 100644
+--- a/net/ipv6/xfrm6_state.c
++++ b/net/ipv6/xfrm6_state.c
+@@ -174,10 +174,12 @@ int xfrm6_extract_header(struct sk_buff *skb)
+ {
+ 	struct ipv6hdr *iph = ipv6_hdr(skb);
+ 
++	XFRM_MODE_SKB_CB(skb)->ihl = sizeof(*iph);
+ 	XFRM_MODE_SKB_CB(skb)->id = 0;
+ 	XFRM_MODE_SKB_CB(skb)->frag_off = htons(IP_DF);
+ 	XFRM_MODE_SKB_CB(skb)->tos = ipv6_get_dsfield(iph);
+ 	XFRM_MODE_SKB_CB(skb)->ttl = iph->hop_limit;
++	XFRM_MODE_SKB_CB(skb)->optlen = 0;
+ 	memcpy(XFRM_MODE_SKB_CB(skb)->flow_lbl, iph->flow_lbl,
+ 	       sizeof(XFRM_MODE_SKB_CB(skb)->flow_lbl));
+ 
+diff --git a/net/irda/irnet/irnet.h b/net/irda/irnet/irnet.h
+index bc2e15c..7873c39 100644
+--- a/net/irda/irnet/irnet.h
++++ b/net/irda/irnet/irnet.h
+@@ -405,7 +405,7 @@ typedef struct irnet_socket
+   /* "pppd" interact directly with us on a /dev/ file */
+   struct file *		file;		/* File descriptor of this instance */
+   /* TTY stuff - to keep "pppd" happy */
+-  struct termios	termios;	/* Various tty flags */
++  struct ktermios	termios;	/* Various tty flags */
+   /* Stuff for the control channel */
+   int			event_index;	/* Last read in the event log */
+ 
+diff --git a/net/key/af_key.c b/net/key/af_key.c
+index 8b5f486..e9ef9af 100644
+--- a/net/key/af_key.c
++++ b/net/key/af_key.c
+@@ -1219,7 +1219,7 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,
+ 		x->sel.prefixlen_s = addr->sadb_address_prefixlen;
+ 	}
+ 
+-	if (!x->sel.family)
++	if (x->props.mode == XFRM_MODE_TRANSPORT)
+ 		x->sel.family = x->props.family;
+ 
+ 	if (ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1]) {
+diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
+index 9712716..c22d6b6 100644
+--- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
++++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
+@@ -322,15 +322,6 @@ next_sge:
+ 		ctxt->direction = DMA_FROM_DEVICE;
+ 		clear_bit(RDMACTXT_F_READ_DONE, &ctxt->flags);
+ 		clear_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags);
+-		if ((ch+1)->rc_discrim == 0) {
+-			/*
+-			 * Checked in sq_cq_reap to see if we need to
+-			 * be enqueued
+-			 */
+-			set_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags);
+-			ctxt->next = hdr_ctxt;
+-			hdr_ctxt->next = head;
+-		}
+ 
+ 		/* Prepare READ WR */
+ 		memset(&read_wr, 0, sizeof read_wr);
+@@ -348,7 +339,17 @@ next_sge:
+ 		rdma_set_ctxt_sge(ctxt, &sge[ch_sge_ary[ch_no].start],
+ 				  &sgl_offset,
+ 				  read_wr.num_sge);
+-
++		if (((ch+1)->rc_discrim == 0) &&
++		    (read_wr.num_sge == ch_sge_ary[ch_no].count)) {
++			/*
++			 * Mark the last RDMA_READ with a bit to
++			 * indicate all RPC data has been fetched from
++			 * the client and the RPC needs to be enqueued.
++			 */
++			set_bit(RDMACTXT_F_LAST_CTXT, &ctxt->flags);
++			ctxt->next = hdr_ctxt;
++			hdr_ctxt->next = head;
++		}
+ 		/* Post the read */
+ 		err = svc_rdma_send(xprt, &read_wr);
+ 		if (err) {
+diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
+index 62188c6..7527940 100644
+--- a/net/xfrm/xfrm_input.c
++++ b/net/xfrm/xfrm_input.c
+@@ -84,14 +84,21 @@ int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq)
+ 
+ int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb)
+ {
++	struct xfrm_mode *inner_mode = x->inner_mode;
+ 	int err;
+ 
+ 	err = x->outer_mode->afinfo->extract_input(x, skb);
+ 	if (err)
+ 		return err;
+ 
+-	skb->protocol = x->inner_mode->afinfo->eth_proto;
+-	return x->inner_mode->input2(x, skb);
++	if (x->sel.family == AF_UNSPEC) {
++		inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
++		if (inner_mode == NULL)
++			return -EAFNOSUPPORT;
++	}
++
++	skb->protocol = inner_mode->afinfo->eth_proto;
++	return inner_mode->input2(x, skb);
+ }
+ EXPORT_SYMBOL(xfrm_prepare_input);
+ 
+@@ -101,6 +108,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
+ 	__be32 seq;
+ 	struct xfrm_state *x;
+ 	xfrm_address_t *daddr;
++	struct xfrm_mode *inner_mode;
+ 	unsigned int family;
+ 	int decaps = 0;
+ 	int async = 0;
+@@ -207,7 +215,15 @@ resume:
+ 
+ 		XFRM_MODE_SKB_CB(skb)->protocol = nexthdr;
+ 
+-		if (x->inner_mode->input(x, skb)) {
++		inner_mode = x->inner_mode;
++
++		if (x->sel.family == AF_UNSPEC) {
++			inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
++			if (inner_mode == NULL)
++				goto drop;
++		}
++
++		if (inner_mode->input(x, skb)) {
+ 			XFRM_INC_STATS(LINUX_MIB_XFRMINSTATEMODEERROR);
+ 			goto drop;
+ 		}
+diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
+index 569d377..2519129 100644
+--- a/net/xfrm/xfrm_output.c
++++ b/net/xfrm/xfrm_output.c
+@@ -124,7 +124,7 @@ int xfrm_output_resume(struct sk_buff *skb, int err)
+ 		if (!x)
+ 			return dst_output(skb);
+ 
+-		err = nf_hook(x->inner_mode->afinfo->family,
++		err = nf_hook(skb->dst->ops->family,
+ 			      NF_INET_POST_ROUTING, skb,
+ 			      NULL, skb->dst->dev, xfrm_output2);
+ 		if (unlikely(err != 1))
+@@ -193,4 +193,20 @@ int xfrm_output(struct sk_buff *skb)
+ 
+ 	return xfrm_output2(skb);
+ }
++
++int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb)
++{
++	struct xfrm_mode *inner_mode;
++	if (x->sel.family == AF_UNSPEC)
++		inner_mode = xfrm_ip2inner_mode(x,
++				xfrm_af2proto(skb->dst->ops->family));
++	else
++		inner_mode = x->inner_mode;
++
++	if (inner_mode == NULL)
++		return -EAFNOSUPPORT;
++	return inner_mode->afinfo->extract_output(x, skb);
++}
++
+ EXPORT_SYMBOL_GPL(xfrm_output);
++EXPORT_SYMBOL_GPL(xfrm_inner_extract_output);
+diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
+index 7ba65e8..58f1f93 100644
+--- a/net/xfrm/xfrm_state.c
++++ b/net/xfrm/xfrm_state.c
+@@ -388,6 +388,8 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
+ 	kfree(x->coaddr);
+ 	if (x->inner_mode)
+ 		xfrm_put_mode(x->inner_mode);
++	if (x->inner_mode_iaf)
++		xfrm_put_mode(x->inner_mode_iaf);
+ 	if (x->outer_mode)
+ 		xfrm_put_mode(x->outer_mode);
+ 	if (x->type) {
+@@ -523,6 +525,8 @@ struct xfrm_state *xfrm_state_alloc(void)
+ 		x->lft.hard_packet_limit = XFRM_INF;
+ 		x->replay_maxage = 0;
+ 		x->replay_maxdiff = 0;
++		x->inner_mode = NULL;
++		x->inner_mode_iaf = NULL;
+ 		spin_lock_init(&x->lock);
+ 	}
+ 	return x;
+@@ -796,7 +800,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr,
+ 			      selector.
+ 			 */
+ 			if (x->km.state == XFRM_STATE_VALID) {
+-				if (!xfrm_selector_match(&x->sel, fl, x->sel.family) ||
++				if ((x->sel.family && !xfrm_selector_match(&x->sel, fl, x->sel.family)) ||
+ 				    !security_xfrm_state_pol_flow_match(x, pol, fl))
+ 					continue;
+ 				if (!best ||
+@@ -1944,6 +1948,7 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu)
+ int xfrm_init_state(struct xfrm_state *x)
+ {
+ 	struct xfrm_state_afinfo *afinfo;
++	struct xfrm_mode *inner_mode;
+ 	int family = x->props.family;
+ 	int err;
+ 
+@@ -1962,13 +1967,48 @@ int xfrm_init_state(struct xfrm_state *x)
+ 		goto error;
+ 
+ 	err = -EPROTONOSUPPORT;
+-	x->inner_mode = xfrm_get_mode(x->props.mode, x->sel.family);
+-	if (x->inner_mode == NULL)
+-		goto error;
+ 
+-	if (!(x->inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) &&
+-	    family != x->sel.family)
+-		goto error;
++	if (x->sel.family != AF_UNSPEC) {
++		inner_mode = xfrm_get_mode(x->props.mode, x->sel.family);
++		if (inner_mode == NULL)
++			goto error;
++
++		if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) &&
++		    family != x->sel.family) {
++			xfrm_put_mode(inner_mode);
++			goto error;
++		}
++
++		x->inner_mode = inner_mode;
++	} else {
++		struct xfrm_mode *inner_mode_iaf;
++
++		inner_mode = xfrm_get_mode(x->props.mode, AF_INET);
++		if (inner_mode == NULL)
++			goto error;
++
++		if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL)) {
++			xfrm_put_mode(inner_mode);
++			goto error;
++		}
++
++		inner_mode_iaf = xfrm_get_mode(x->props.mode, AF_INET6);
++		if (inner_mode_iaf == NULL)
++			goto error;
++
++		if (!(inner_mode_iaf->flags & XFRM_MODE_FLAG_TUNNEL)) {
++			xfrm_put_mode(inner_mode_iaf);
++			goto error;
++		}
++
++		if (x->props.family == AF_INET) {
++			x->inner_mode = inner_mode;
++			x->inner_mode_iaf = inner_mode_iaf;
++		} else {
++			x->inner_mode = inner_mode_iaf;
++			x->inner_mode_iaf = inner_mode;
++		}
++	}
+ 
+ 	x->type = xfrm_get_type(x->id.proto, family);
+ 	if (x->type == NULL)
+diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
+index f971ca5..5d96f27 100644
+--- a/net/xfrm/xfrm_user.c
++++ b/net/xfrm/xfrm_user.c
+@@ -288,12 +288,9 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *
+ 	memcpy(&x->props.saddr, &p->saddr, sizeof(x->props.saddr));
+ 	x->props.flags = p->flags;
+ 
+-	/*
+-	 * Set inner address family if the KM left it as zero.
+-	 * See comment in validate_tmpl.
+-	 */
+-	if (!x->sel.family)
++	if (x->props.mode == XFRM_MODE_TRANSPORT)
+ 		x->sel.family = p->family;
++
+ }
+ 
+ /*

Modified: dists/trunk/linux-2.6/debian/patches/series/1~experimental.1
==============================================================================
--- dists/trunk/linux-2.6/debian/patches/series/1~experimental.1	(original)
+++ dists/trunk/linux-2.6/debian/patches/series/1~experimental.1	Fri Mar 28 17:54:14 2008
@@ -1,4 +1,4 @@
-+ bugfix/all/patch-2.6.25-rc7-git2
++ bugfix/all/patch-2.6.25-rc7-git3
 + debian/version.patch
 + debian/kernelvariables.patch
 + debian/doc-build-parallel.patch



More information about the Kernel-svn-changes mailing list