[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