--- /dev/null
+From davem@davemloft.net Tue Jan 3 12:06:53 2012
+From: David Miller <davem@davemloft.net>
+Date: Mon, 26 Dec 2011 14:59:20 -0500 (EST)
+Subject: mpt2sas crashes on shutdown
+To: stable@vger.kernel.org
+Cc: linux-scsi@vger.kernel.org, nagalakshmi.nandigama@lsi.com
+Message-ID: <20111226.145920.1088076837634135764.davem@davemloft.net>
+
+From: David Miller <davem@davemloft.net>
+
+[Fixed differently in 3.2]
+
+The mpt2sas driver accesses I/O space as virtual addresses when
+saving and restoring the MSIX table, this only works by luck on x86.
+
+One needs to use the appropriate {read,write}{b,w,l}() APIs.
+
+This is fixed in v3.2.x because all of this code got rewritten for
+NUMA I/O support.
+
+But both 3.0.x and 3.1.x still have this bug, and my Niagara sparc
+machines crash on shutdown every single time due to this bug making my
+-stable work more difficult than it needs to be.
+
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Cc: Eric Moore <Eric.Moore@lsi.com>
+Cc: Nagalakshmi Nandigama <nagalakshmi.nandigama@lsi.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/scsi/mpt2sas/mpt2sas_base.c | 6 +++---
+ drivers/scsi/mpt2sas/mpt2sas_base.h | 2 +-
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/scsi/mpt2sas/mpt2sas_base.c
++++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
+@@ -1096,7 +1096,7 @@ _base_save_msix_table(struct MPT2SAS_ADA
+ return;
+
+ for (i = 0; i < ioc->msix_vector_count; i++)
+- ioc->msix_table_backup[i] = ioc->msix_table[i];
++ ioc->msix_table_backup[i] = readl(&ioc->msix_table[i]);
+ }
+
+ /**
+@@ -1113,7 +1113,7 @@ _base_restore_msix_table(struct MPT2SAS_
+ return;
+
+ for (i = 0; i < ioc->msix_vector_count; i++)
+- ioc->msix_table[i] = ioc->msix_table_backup[i];
++ writel(ioc->msix_table_backup[i], &ioc->msix_table[i]);
+ }
+
+ /**
+@@ -1144,7 +1144,7 @@ _base_check_enable_msix(struct MPT2SAS_A
+ /* get msix table */
+ pci_read_config_dword(ioc->pdev, base + 4, &msix_table_offset);
+ msix_table_offset &= 0xFFFFFFF8;
+- ioc->msix_table = (u32 *)((void *)ioc->chip + msix_table_offset);
++ ioc->msix_table = ((void __iomem *)ioc->chip + msix_table_offset);
+
+ dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "msix is supported, "
+ "vector_count(%d), table_offset(0x%08x), table(%p)\n", ioc->name,
+--- a/drivers/scsi/mpt2sas/mpt2sas_base.h
++++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
+@@ -768,7 +768,7 @@ struct MPT2SAS_ADAPTER {
+
+ u8 msix_enable;
+ u16 msix_vector_count;
+- u32 *msix_table;
++ u32 __iomem *msix_table;
+ u32 *msix_table_backup;
+ u32 ioc_reset_count;
+
watchdog-hpwdt-changes-to-handle-nx-secure-bit-in-32bit-path.patch
drm-radeon-kms-bail-on-btc-parts-if-mc-ucode-is-missing.patch
mm-hugetlb-fix-non-atomic-enqueue-of-huge-page.patch
+mpt2sas-crashes-on-shutdown.patch
+sparc64-fix-msiq-hv-call-ordering-in-pci_sun4v_msiq_build_irq.patch
+sparc32-be-less-strict-in-matching-lo-part-of-relocation.patch
+sparc64-patch-sun4v-code-sequences-properly-on-module-load.patch
+sparc-kill-custom-io_remap_pfn_range.patch
+sparc32-remove-non-kernel-code-from-memcpy-implementation.patch
+sparc32-remove-uses-of-g7-in-memcpy-implementation.patch
+sparc32-correct-the-return-value-of-memcpy.patch
+sparc64-fix-masking-and-shifting-in-vis-fpcmp-emulation.patch
+sparc-fix-handling-of-orig_i0-wrt.-debugging-when-restarting-syscalls.patch
--- /dev/null
+From d16b87e22fe215f640a5a3e95dfd34d6ff182d7e Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Mon, 26 Dec 2011 12:30:13 -0500
+Subject: sparc: Fix handling of orig_i0 wrt. debugging when restarting syscalls.
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ A combination of upstream commits 1d299bc7732c34d85bd43ac1a8745f5a2fed2078 and
+ e88d2468718b0789b4c33da2f7e1cef2a1eee279 ]
+
+Although we provide a proper way for a debugger to control whether
+syscall restart occurs, we run into problems because orig_i0 is not
+saved and restored properly.
+
+Luckily we can solve this problem without having to make debuggers
+aware of the issue. Across system calls, several registers are
+considered volatile and can be safely clobbered.
+
+Therefore we use the pt_regs save area of one of those registers, %g6,
+as a place to save and restore orig_i0.
+
+Debuggers transparently will do the right thing because they save and
+restore this register already.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/kernel/signal32.c | 18 ++++++++++--------
+ arch/sparc/kernel/signal_32.c | 30 +++++++++++++++++++++++++-----
+ arch/sparc/kernel/signal_64.c | 42 ++++++++++++++++++++++++++++--------------
+ 3 files changed, 63 insertions(+), 27 deletions(-)
+
+--- a/arch/sparc/kernel/signal32.c
++++ b/arch/sparc/kernel/signal32.c
+@@ -829,21 +829,23 @@ static inline void syscall_restart32(uns
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ */
+-void do_signal32(sigset_t *oldset, struct pt_regs * regs,
+- int restart_syscall, unsigned long orig_i0)
++void do_signal32(sigset_t *oldset, struct pt_regs * regs)
+ {
+ struct k_sigaction ka;
++ unsigned long orig_i0;
++ int restart_syscall;
+ siginfo_t info;
+ int signr;
+
+ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+
+- /* If the debugger messes with the program counter, it clears
+- * the "in syscall" bit, directing us to not perform a syscall
+- * restart.
+- */
+- if (restart_syscall && !pt_regs_is_syscall(regs))
+- restart_syscall = 0;
++ restart_syscall = 0;
++ orig_i0 = 0;
++ if (pt_regs_is_syscall(regs) &&
++ (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
++ restart_syscall = 1;
++ orig_i0 = regs->u_regs[UREG_G6];
++ }
+
+ if (signr > 0) {
+ if (restart_syscall)
+--- a/arch/sparc/kernel/signal_32.c
++++ b/arch/sparc/kernel/signal_32.c
+@@ -525,10 +525,26 @@ static void do_signal(struct pt_regs *re
+ siginfo_t info;
+ int signr;
+
++ /* It's a lot of work and synchronization to add a new ptrace
++ * register for GDB to save and restore in order to get
++ * orig_i0 correct for syscall restarts when debugging.
++ *
++ * Although it should be the case that most of the global
++ * registers are volatile across a system call, glibc already
++ * depends upon that fact that we preserve them. So we can't
++ * just use any global register to save away the orig_i0 value.
++ *
++ * In particular %g2, %g3, %g4, and %g5 are all assumed to be
++ * preserved across a system call trap by various pieces of
++ * code in glibc.
++ *
++ * %g7 is used as the "thread register". %g6 is not used in
++ * any fixed manner. %g6 is used as a scratch register and
++ * a compiler temporary, but it's value is never used across
++ * a system call. Therefore %g6 is usable for orig_i0 storage.
++ */
+ if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C))
+- restart_syscall = 1;
+- else
+- restart_syscall = 0;
++ regs->u_regs[UREG_G6] = orig_i0;
+
+ if (test_thread_flag(TIF_RESTORE_SIGMASK))
+ oldset = ¤t->saved_sigmask;
+@@ -541,8 +557,12 @@ static void do_signal(struct pt_regs *re
+ * the software "in syscall" bit, directing us to not perform
+ * a syscall restart.
+ */
+- if (restart_syscall && !pt_regs_is_syscall(regs))
+- restart_syscall = 0;
++ restart_syscall = 0;
++ if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C)) {
++ restart_syscall = 1;
++ orig_i0 = regs->u_regs[UREG_G6];
++ }
++
+
+ if (signr > 0) {
+ if (restart_syscall)
+--- a/arch/sparc/kernel/signal_64.c
++++ b/arch/sparc/kernel/signal_64.c
+@@ -535,11 +535,27 @@ static void do_signal(struct pt_regs *re
+ siginfo_t info;
+ int signr;
+
++ /* It's a lot of work and synchronization to add a new ptrace
++ * register for GDB to save and restore in order to get
++ * orig_i0 correct for syscall restarts when debugging.
++ *
++ * Although it should be the case that most of the global
++ * registers are volatile across a system call, glibc already
++ * depends upon that fact that we preserve them. So we can't
++ * just use any global register to save away the orig_i0 value.
++ *
++ * In particular %g2, %g3, %g4, and %g5 are all assumed to be
++ * preserved across a system call trap by various pieces of
++ * code in glibc.
++ *
++ * %g7 is used as the "thread register". %g6 is not used in
++ * any fixed manner. %g6 is used as a scratch register and
++ * a compiler temporary, but it's value is never used across
++ * a system call. Therefore %g6 is usable for orig_i0 storage.
++ */
+ if (pt_regs_is_syscall(regs) &&
+- (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
+- restart_syscall = 1;
+- } else
+- restart_syscall = 0;
++ (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
++ regs->u_regs[UREG_G6] = orig_i0;
+
+ if (current_thread_info()->status & TS_RESTORE_SIGMASK)
+ oldset = ¤t->saved_sigmask;
+@@ -548,22 +564,20 @@ static void do_signal(struct pt_regs *re
+
+ #ifdef CONFIG_COMPAT
+ if (test_thread_flag(TIF_32BIT)) {
+- extern void do_signal32(sigset_t *, struct pt_regs *,
+- int restart_syscall,
+- unsigned long orig_i0);
+- do_signal32(oldset, regs, restart_syscall, orig_i0);
++ extern void do_signal32(sigset_t *, struct pt_regs *);
++ do_signal32(oldset, regs);
+ return;
+ }
+ #endif
+
+ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+
+- /* If the debugger messes with the program counter, it clears
+- * the software "in syscall" bit, directing us to not perform
+- * a syscall restart.
+- */
+- if (restart_syscall && !pt_regs_is_syscall(regs))
+- restart_syscall = 0;
++ restart_syscall = 0;
++ if (pt_regs_is_syscall(regs) &&
++ (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
++ restart_syscall = 1;
++ orig_i0 = regs->u_regs[UREG_G6];
++ }
+
+ if (signr > 0) {
+ if (restart_syscall)
--- /dev/null
+From 81f6423527575fc9b9ab9c79784078ba93ed8d31 Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Thu, 17 Nov 2011 18:17:59 -0800
+Subject: sparc: Kill custom io_remap_pfn_range().
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit 3e37fd3153ac95088a74f5e7c569f7567e9f993a ]
+
+To handle the large physical addresses, just make a simple wrapper
+around remap_pfn_range() like MIPS does.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/include/asm/pgtable_32.h | 20 +++-
+ arch/sparc/include/asm/pgtable_64.h | 20 +++-
+ arch/sparc/mm/Makefile | 1
+ arch/sparc/mm/generic_32.c | 98 ---------------------
+ arch/sparc/mm/generic_64.c | 164 ------------------------------------
+ 5 files changed, 32 insertions(+), 271 deletions(-)
+ delete mode 100644 arch/sparc/mm/generic_32.c
+ delete mode 100644 arch/sparc/mm/generic_64.c
+
+--- a/arch/sparc/include/asm/pgtable_32.h
++++ b/arch/sparc/include/asm/pgtable_32.h
+@@ -431,10 +431,6 @@ extern unsigned long *sparc_valid_addr_b
+ #define kern_addr_valid(addr) \
+ (test_bit(__pa((unsigned long)(addr))>>20, sparc_valid_addr_bitmap))
+
+-extern int io_remap_pfn_range(struct vm_area_struct *vma,
+- unsigned long from, unsigned long pfn,
+- unsigned long size, pgprot_t prot);
+-
+ /*
+ * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
+ * its high 4 bits. These macros/functions put it there or get it from there.
+@@ -443,6 +439,22 @@ extern int io_remap_pfn_range(struct vm_
+ #define GET_IOSPACE(pfn) (pfn >> (BITS_PER_LONG - 4))
+ #define GET_PFN(pfn) (pfn & 0x0fffffffUL)
+
++extern int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long,
++ unsigned long, pgprot_t);
++
++static inline int io_remap_pfn_range(struct vm_area_struct *vma,
++ unsigned long from, unsigned long pfn,
++ unsigned long size, pgprot_t prot)
++{
++ unsigned long long offset, space, phys_base;
++
++ offset = ((unsigned long long) GET_PFN(pfn)) << PAGE_SHIFT;
++ space = GET_IOSPACE(pfn);
++ phys_base = offset | (space << 32ULL);
++
++ return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
++}
++
+ #define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+ #define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
+ ({ \
+--- a/arch/sparc/include/asm/pgtable_64.h
++++ b/arch/sparc/include/asm/pgtable_64.h
+@@ -750,10 +750,6 @@ static inline bool kern_addr_valid(unsig
+
+ extern int page_in_phys_avail(unsigned long paddr);
+
+-extern int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
+- unsigned long pfn,
+- unsigned long size, pgprot_t prot);
+-
+ /*
+ * For sparc32&64, the pfn in io_remap_pfn_range() carries <iospace> in
+ * its high 4 bits. These macros/functions put it there or get it from there.
+@@ -762,6 +758,22 @@ extern int io_remap_pfn_range(struct vm_
+ #define GET_IOSPACE(pfn) (pfn >> (BITS_PER_LONG - 4))
+ #define GET_PFN(pfn) (pfn & 0x0fffffffffffffffUL)
+
++extern int remap_pfn_range(struct vm_area_struct *, unsigned long, unsigned long,
++ unsigned long, pgprot_t);
++
++static inline int io_remap_pfn_range(struct vm_area_struct *vma,
++ unsigned long from, unsigned long pfn,
++ unsigned long size, pgprot_t prot)
++{
++ unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
++ int space = GET_IOSPACE(pfn);
++ unsigned long phys_base;
++
++ phys_base = offset | (((unsigned long) space) << 32UL);
++
++ return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot);
++}
++
+ #include <asm-generic/pgtable.h>
+
+ /* We provide our own get_unmapped_area to cope with VA holes and
+--- a/arch/sparc/mm/Makefile
++++ b/arch/sparc/mm/Makefile
+@@ -8,7 +8,6 @@ obj-$(CONFIG_SPARC64) += ultra.o tlb.o
+ obj-y += fault_$(BITS).o
+ obj-y += init_$(BITS).o
+ obj-$(CONFIG_SPARC32) += loadmmu.o
+-obj-y += generic_$(BITS).o
+ obj-$(CONFIG_SPARC32) += extable.o btfixup.o srmmu.o iommu.o io-unit.o
+ obj-$(CONFIG_SPARC32) += hypersparc.o viking.o tsunami.o swift.o
+ obj-$(CONFIG_SPARC_LEON)+= leon_mm.o
+--- a/arch/sparc/mm/generic_32.c
++++ /dev/null
+@@ -1,98 +0,0 @@
+-/*
+- * generic.c: Generic Sparc mm routines that are not dependent upon
+- * MMU type but are Sparc specific.
+- *
+- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/mm.h>
+-#include <linux/swap.h>
+-#include <linux/pagemap.h>
+-
+-#include <asm/pgalloc.h>
+-#include <asm/pgtable.h>
+-#include <asm/page.h>
+-#include <asm/cacheflush.h>
+-#include <asm/tlbflush.h>
+-
+-/* Remap IO memory, the same way as remap_pfn_range(), but use
+- * the obio memory space.
+- *
+- * They use a pgprot that sets PAGE_IO and does not check the
+- * mem_map table as this is independent of normal memory.
+- */
+-static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte, unsigned long address, unsigned long size,
+- unsigned long offset, pgprot_t prot, int space)
+-{
+- unsigned long end;
+-
+- address &= ~PMD_MASK;
+- end = address + size;
+- if (end > PMD_SIZE)
+- end = PMD_SIZE;
+- do {
+- set_pte_at(mm, address, pte, mk_pte_io(offset, prot, space));
+- address += PAGE_SIZE;
+- offset += PAGE_SIZE;
+- pte++;
+- } while (address < end);
+-}
+-
+-static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
+- unsigned long offset, pgprot_t prot, int space)
+-{
+- unsigned long end;
+-
+- address &= ~PGDIR_MASK;
+- end = address + size;
+- if (end > PGDIR_SIZE)
+- end = PGDIR_SIZE;
+- offset -= address;
+- do {
+- pte_t *pte = pte_alloc_map(mm, NULL, pmd, address);
+- if (!pte)
+- return -ENOMEM;
+- io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space);
+- address = (address + PMD_SIZE) & PMD_MASK;
+- pmd++;
+- } while (address < end);
+- return 0;
+-}
+-
+-int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
+- unsigned long pfn, unsigned long size, pgprot_t prot)
+-{
+- int error = 0;
+- pgd_t * dir;
+- unsigned long beg = from;
+- unsigned long end = from + size;
+- struct mm_struct *mm = vma->vm_mm;
+- int space = GET_IOSPACE(pfn);
+- unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
+-
+- /* See comment in mm/memory.c remap_pfn_range */
+- vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
+- vma->vm_pgoff = (offset >> PAGE_SHIFT) |
+- ((unsigned long)space << 28UL);
+-
+- offset -= from;
+- dir = pgd_offset(mm, from);
+- flush_cache_range(vma, beg, end);
+-
+- while (from < end) {
+- pmd_t *pmd = pmd_alloc(mm, dir, from);
+- error = -ENOMEM;
+- if (!pmd)
+- break;
+- error = io_remap_pmd_range(mm, pmd, from, end - from, offset + from, prot, space);
+- if (error)
+- break;
+- from = (from + PGDIR_SIZE) & PGDIR_MASK;
+- dir++;
+- }
+-
+- flush_tlb_range(vma, beg, end);
+- return error;
+-}
+-EXPORT_SYMBOL(io_remap_pfn_range);
+--- a/arch/sparc/mm/generic_64.c
++++ /dev/null
+@@ -1,164 +0,0 @@
+-/*
+- * generic.c: Generic Sparc mm routines that are not dependent upon
+- * MMU type but are Sparc specific.
+- *
+- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+- */
+-
+-#include <linux/kernel.h>
+-#include <linux/mm.h>
+-#include <linux/swap.h>
+-#include <linux/pagemap.h>
+-
+-#include <asm/pgalloc.h>
+-#include <asm/pgtable.h>
+-#include <asm/page.h>
+-#include <asm/tlbflush.h>
+-
+-/* Remap IO memory, the same way as remap_pfn_range(), but use
+- * the obio memory space.
+- *
+- * They use a pgprot that sets PAGE_IO and does not check the
+- * mem_map table as this is independent of normal memory.
+- */
+-static inline void io_remap_pte_range(struct mm_struct *mm, pte_t * pte,
+- unsigned long address,
+- unsigned long size,
+- unsigned long offset, pgprot_t prot,
+- int space)
+-{
+- unsigned long end;
+-
+- /* clear hack bit that was used as a write_combine side-effect flag */
+- offset &= ~0x1UL;
+- address &= ~PMD_MASK;
+- end = address + size;
+- if (end > PMD_SIZE)
+- end = PMD_SIZE;
+- do {
+- pte_t entry;
+- unsigned long curend = address + PAGE_SIZE;
+-
+- entry = mk_pte_io(offset, prot, space, PAGE_SIZE);
+- if (!(address & 0xffff)) {
+- if (PAGE_SIZE < (4 * 1024 * 1024) &&
+- !(address & 0x3fffff) &&
+- !(offset & 0x3ffffe) &&
+- end >= address + 0x400000) {
+- entry = mk_pte_io(offset, prot, space,
+- 4 * 1024 * 1024);
+- curend = address + 0x400000;
+- offset += 0x400000;
+- } else if (PAGE_SIZE < (512 * 1024) &&
+- !(address & 0x7ffff) &&
+- !(offset & 0x7fffe) &&
+- end >= address + 0x80000) {
+- entry = mk_pte_io(offset, prot, space,
+- 512 * 1024 * 1024);
+- curend = address + 0x80000;
+- offset += 0x80000;
+- } else if (PAGE_SIZE < (64 * 1024) &&
+- !(offset & 0xfffe) &&
+- end >= address + 0x10000) {
+- entry = mk_pte_io(offset, prot, space,
+- 64 * 1024);
+- curend = address + 0x10000;
+- offset += 0x10000;
+- } else
+- offset += PAGE_SIZE;
+- } else
+- offset += PAGE_SIZE;
+-
+- if (pte_write(entry))
+- entry = pte_mkdirty(entry);
+- do {
+- BUG_ON(!pte_none(*pte));
+- set_pte_at(mm, address, pte, entry);
+- address += PAGE_SIZE;
+- pte_val(entry) += PAGE_SIZE;
+- pte++;
+- } while (address < curend);
+- } while (address < end);
+-}
+-
+-static inline int io_remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
+- unsigned long offset, pgprot_t prot, int space)
+-{
+- unsigned long end;
+-
+- address &= ~PGDIR_MASK;
+- end = address + size;
+- if (end > PGDIR_SIZE)
+- end = PGDIR_SIZE;
+- offset -= address;
+- do {
+- pte_t *pte = pte_alloc_map(mm, NULL, pmd, address);
+- if (!pte)
+- return -ENOMEM;
+- io_remap_pte_range(mm, pte, address, end - address, address + offset, prot, space);
+- pte_unmap(pte);
+- address = (address + PMD_SIZE) & PMD_MASK;
+- pmd++;
+- } while (address < end);
+- return 0;
+-}
+-
+-static inline int io_remap_pud_range(struct mm_struct *mm, pud_t * pud, unsigned long address, unsigned long size,
+- unsigned long offset, pgprot_t prot, int space)
+-{
+- unsigned long end;
+-
+- address &= ~PUD_MASK;
+- end = address + size;
+- if (end > PUD_SIZE)
+- end = PUD_SIZE;
+- offset -= address;
+- do {
+- pmd_t *pmd = pmd_alloc(mm, pud, address);
+- if (!pud)
+- return -ENOMEM;
+- io_remap_pmd_range(mm, pmd, address, end - address, address + offset, prot, space);
+- address = (address + PUD_SIZE) & PUD_MASK;
+- pud++;
+- } while (address < end);
+- return 0;
+-}
+-
+-int io_remap_pfn_range(struct vm_area_struct *vma, unsigned long from,
+- unsigned long pfn, unsigned long size, pgprot_t prot)
+-{
+- int error = 0;
+- pgd_t * dir;
+- unsigned long beg = from;
+- unsigned long end = from + size;
+- struct mm_struct *mm = vma->vm_mm;
+- int space = GET_IOSPACE(pfn);
+- unsigned long offset = GET_PFN(pfn) << PAGE_SHIFT;
+- unsigned long phys_base;
+-
+- phys_base = offset | (((unsigned long) space) << 32UL);
+-
+- /* See comment in mm/memory.c remap_pfn_range */
+- vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
+- vma->vm_pgoff = phys_base >> PAGE_SHIFT;
+-
+- offset -= from;
+- dir = pgd_offset(mm, from);
+- flush_cache_range(vma, beg, end);
+-
+- while (from < end) {
+- pud_t *pud = pud_alloc(mm, dir, from);
+- error = -ENOMEM;
+- if (!pud)
+- break;
+- error = io_remap_pud_range(mm, pud, from, end - from, offset + from, prot, space);
+- if (error)
+- break;
+- from = (from + PGDIR_SIZE) & PGDIR_MASK;
+- dir++;
+- }
+-
+- flush_tlb_range(vma, beg, end);
+- return error;
+-}
+-EXPORT_SYMBOL(io_remap_pfn_range);
--- /dev/null
+From 8c8f38c77fccfe61501d26016b9c66c231a588ac Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Wed, 14 Dec 2011 10:05:22 -0800
+Subject: sparc32: Be less strict in matching %lo part of relocation.
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit b1f44e13a525d2ffb7d5afe2273b7169d6f2222e ]
+
+The "(insn & 0x01800000) != 0x01800000" test matches 'restore'
+but that is a legitimate place to see the %lo() part of a 32-bit
+symbol relocation, particularly in tail calls.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Tested-by: Sergei Trofimovich <slyfox@gentoo.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/mm/btfixup.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/arch/sparc/mm/btfixup.c
++++ b/arch/sparc/mm/btfixup.c
+@@ -302,8 +302,7 @@ void __init btfixup(void)
+ case 'i': /* INT */
+ if ((insn & 0xc1c00000) == 0x01000000) /* %HI */
+ set_addr(addr, q[1], fmangled, (insn & 0xffc00000) | (p[1] >> 10));
+- else if ((insn & 0x80002000) == 0x80002000 &&
+- (insn & 0x01800000) != 0x01800000) /* %LO */
++ else if ((insn & 0x80002000) == 0x80002000) /* %LO */
+ set_addr(addr, q[1], fmangled, (insn & 0xffffe000) | (p[1] & 0x3ff));
+ else {
+ prom_printf(insn_i, p, addr, insn);
--- /dev/null
+From 45b26bff9ac2a8df2239ed5ed90b092f1a7d033c Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Wed, 19 Oct 2011 15:31:55 -0700
+Subject: sparc32: Correct the return value of memcpy.
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit a52312b88c8103e965979a79a07f6b34af82ca4b ]
+
+Properly return the original destination buffer pointer.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Tested-by: Kjetil Oftedal <oftedal@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/lib/memcpy.S | 22 +++++++---------------
+ 1 file changed, 7 insertions(+), 15 deletions(-)
+
+--- a/arch/sparc/lib/memcpy.S
++++ b/arch/sparc/lib/memcpy.S
+@@ -13,14 +13,6 @@
+ .align 4; \
+ x:
+
+-
+-/* In kernel these functions don't return a value.
+- * One should use macros in asm/string.h for that purpose.
+- * We return 0, so that bugs are more apparent.
+- */
+-#define SETUP_RETL
+-#define RETL_INSN clr %o0
+-
+ /* Both these macros have to start with exactly the same insn */
+ #define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \
+ ldd [%src + (offset) + 0x00], %t0; \
+@@ -154,7 +146,7 @@ FUNC(__memmove)
+ #endif
+ FUNC(memmove)
+ cmp %o0, %o1
+- SETUP_RETL
++ mov %o0, %g7
+ bleu 9f
+ sub %o0, %o1, %o4
+
+@@ -178,7 +170,7 @@ FUNC(memmove)
+ sub %o0, 1, %o0
+
+ retl
+- RETL_INSN
++ mov %g7, %o0
+
+ /* NOTE: This code is executed just for the cases,
+ where %src (=%o1) & 3 is != 0.
+@@ -212,7 +204,7 @@ FUNC(memmove)
+ FUNC(memcpy) /* %o0=dst %o1=src %o2=len */
+
+ sub %o0, %o1, %o4
+- SETUP_RETL
++ mov %o0, %g7
+ 9:
+ andcc %o4, 3, %o5
+ 0:
+@@ -308,7 +300,7 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len
+ stb %g2, [%o0]
+ 1:
+ retl
+- RETL_INSN
++ mov %g7, %o0
+
+ 82: /* ldd_std */
+ MOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
+@@ -373,7 +365,7 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len
+ stb %g2, [%o0]
+ 1:
+ retl
+- RETL_INSN
++ mov %g7, %o0
+
+ 86: /* non_aligned */
+ cmp %o2, 6
+@@ -498,7 +490,7 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len
+ stb %g2, [%i0 + 4]
+ 1:
+ ret
+- restore %g0, %g0, %o0
++ restore %g7, %g0, %o0
+
+ 88: /* short_end */
+
+@@ -529,7 +521,7 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len
+ stb %g2, [%o0]
+ 1:
+ retl
+- RETL_INSN
++ mov %g7, %o0
+
+ 90: /* short_aligned_end */
+ bne 88b
--- /dev/null
+From b1f1286b491efd1a217bea6a74461b08692d511d Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Wed, 19 Oct 2011 15:15:58 -0700
+Subject: sparc32: Remove non-kernel code from memcpy implementation.
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit 045b7de9ca0cf09f1adc3efa467f668b89238390 ]
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Tested-by: Kjetil Oftedal <oftedal@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/lib/memcpy.S | 607 ------------------------------------------------
+ 1 file changed, 2 insertions(+), 605 deletions(-)
+
+--- a/arch/sparc/lib/memcpy.S
++++ b/arch/sparc/lib/memcpy.S
+@@ -7,17 +7,12 @@
+ * Copyright (C) 1996 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
+ */
+
+-#ifdef __KERNEL__
+-
+-#define FUNC(x) \
++#define FUNC(x) \
+ .globl x; \
+ .type x,@function; \
+- .align 4; \
++ .align 4; \
+ x:
+
+-#undef FASTER_REVERSE
+-#undef FASTER_NONALIGNED
+-#define FASTER_ALIGNED
+
+ /* In kernel these functions don't return a value.
+ * One should use macros in asm/string.h for that purpose.
+@@ -26,21 +21,6 @@ x:
+ #define SETUP_RETL
+ #define RETL_INSN clr %o0
+
+-#else
+-
+-/* libc */
+-
+-#include "DEFS.h"
+-
+-#define FASTER_REVERSE
+-#define FASTER_NONALIGNED
+-#define FASTER_ALIGNED
+-
+-#define SETUP_RETL mov %o0, %g6
+-#define RETL_INSN mov %g6, %o0
+-
+-#endif
+-
+ /* Both these macros have to start with exactly the same insn */
+ #define MOVE_BIGCHUNK(src, dst, offset, t0, t1, t2, t3, t4, t5, t6, t7) \
+ ldd [%src + (offset) + 0x00], %t0; \
+@@ -164,30 +144,6 @@ x:
+ .text
+ .align 4
+
+-#ifdef FASTER_REVERSE
+-
+-70: /* rdword_align */
+-
+- andcc %o1, 1, %g0
+- be 4f
+- andcc %o1, 2, %g0
+-
+- ldub [%o1 - 1], %g2
+- sub %o1, 1, %o1
+- stb %g2, [%o0 - 1]
+- sub %o2, 1, %o2
+- be 3f
+- sub %o0, 1, %o0
+-4:
+- lduh [%o1 - 2], %g2
+- sub %o1, 2, %o1
+- sth %g2, [%o0 - 2]
+- sub %o2, 2, %o2
+- b 3f
+- sub %o0, 2, %o0
+-
+-#endif /* FASTER_REVERSE */
+-
+ 0:
+ retl
+ nop ! Only bcopy returns here and it retuns void...
+@@ -207,8 +163,6 @@ FUNC(memmove)
+ bleu 0f
+ andcc %o4, 3, %o5
+
+-#ifndef FASTER_REVERSE
+-
+ add %o1, %o2, %o1
+ add %o0, %o2, %o0
+ sub %o1, 1, %o1
+@@ -226,294 +180,6 @@ FUNC(memmove)
+ retl
+ RETL_INSN
+
+-#else /* FASTER_REVERSE */
+-
+- add %o1, %o2, %o1
+- add %o0, %o2, %o0
+- bne 77f
+- cmp %o2, 15
+- bleu 91f
+- andcc %o1, 3, %g0
+- bne 70b
+-3:
+- andcc %o1, 4, %g0
+-
+- be 2f
+- mov %o2, %g1
+-
+- ld [%o1 - 4], %o4
+- sub %g1, 4, %g1
+- st %o4, [%o0 - 4]
+- sub %o1, 4, %o1
+- sub %o0, 4, %o0
+-2:
+- andcc %g1, 0xffffff80, %g7
+- be 3f
+- andcc %o0, 4, %g0
+-
+- be 74f + 4
+-5:
+- RMOVE_BIGCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
+- RMOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
+- RMOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
+- RMOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
+- subcc %g7, 128, %g7
+- sub %o1, 128, %o1
+- bne 5b
+- sub %o0, 128, %o0
+-3:
+- andcc %g1, 0x70, %g7
+- be 72f
+- andcc %g1, 8, %g0
+-
+- sethi %hi(72f), %o5
+- srl %g7, 1, %o4
+- add %g7, %o4, %o4
+- sub %o1, %g7, %o1
+- sub %o5, %o4, %o5
+- jmpl %o5 + %lo(72f), %g0
+- sub %o0, %g7, %o0
+-
+-71: /* rmemcpy_table */
+- RMOVE_LASTCHUNK(o1, o0, 0x60, g2, g3, g4, g5)
+- RMOVE_LASTCHUNK(o1, o0, 0x50, g2, g3, g4, g5)
+- RMOVE_LASTCHUNK(o1, o0, 0x40, g2, g3, g4, g5)
+- RMOVE_LASTCHUNK(o1, o0, 0x30, g2, g3, g4, g5)
+- RMOVE_LASTCHUNK(o1, o0, 0x20, g2, g3, g4, g5)
+- RMOVE_LASTCHUNK(o1, o0, 0x10, g2, g3, g4, g5)
+- RMOVE_LASTCHUNK(o1, o0, 0x00, g2, g3, g4, g5)
+-
+-72: /* rmemcpy_table_end */
+-
+- be 73f
+- andcc %g1, 4, %g0
+-
+- ldd [%o1 - 0x08], %g2
+- sub %o0, 8, %o0
+- sub %o1, 8, %o1
+- st %g2, [%o0]
+- st %g3, [%o0 + 0x04]
+-
+-73: /* rmemcpy_last7 */
+-
+- be 1f
+- andcc %g1, 2, %g0
+-
+- ld [%o1 - 4], %g2
+- sub %o1, 4, %o1
+- st %g2, [%o0 - 4]
+- sub %o0, 4, %o0
+-1:
+- be 1f
+- andcc %g1, 1, %g0
+-
+- lduh [%o1 - 2], %g2
+- sub %o1, 2, %o1
+- sth %g2, [%o0 - 2]
+- sub %o0, 2, %o0
+-1:
+- be 1f
+- nop
+-
+- ldub [%o1 - 1], %g2
+- stb %g2, [%o0 - 1]
+-1:
+- retl
+- RETL_INSN
+-
+-74: /* rldd_std */
+- RMOVE_BIGALIGNCHUNK(o1, o0, 0x00, o2, o3, o4, o5, g2, g3, g4, g5)
+- RMOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
+- RMOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
+- RMOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
+- subcc %g7, 128, %g7
+- sub %o1, 128, %o1
+- bne 74b
+- sub %o0, 128, %o0
+-
+- andcc %g1, 0x70, %g7
+- be 72b
+- andcc %g1, 8, %g0
+-
+- sethi %hi(72b), %o5
+- srl %g7, 1, %o4
+- add %g7, %o4, %o4
+- sub %o1, %g7, %o1
+- sub %o5, %o4, %o5
+- jmpl %o5 + %lo(72b), %g0
+- sub %o0, %g7, %o0
+-
+-75: /* rshort_end */
+-
+- and %o2, 0xe, %o3
+-2:
+- sethi %hi(76f), %o5
+- sll %o3, 3, %o4
+- sub %o0, %o3, %o0
+- sub %o5, %o4, %o5
+- sub %o1, %o3, %o1
+- jmpl %o5 + %lo(76f), %g0
+- andcc %o2, 1, %g0
+-
+- RMOVE_SHORTCHUNK(o1, o0, 0x0c, g2, g3)
+- RMOVE_SHORTCHUNK(o1, o0, 0x0a, g2, g3)
+- RMOVE_SHORTCHUNK(o1, o0, 0x08, g2, g3)
+- RMOVE_SHORTCHUNK(o1, o0, 0x06, g2, g3)
+- RMOVE_SHORTCHUNK(o1, o0, 0x04, g2, g3)
+- RMOVE_SHORTCHUNK(o1, o0, 0x02, g2, g3)
+- RMOVE_SHORTCHUNK(o1, o0, 0x00, g2, g3)
+-
+-76: /* rshort_table_end */
+-
+- be 1f
+- nop
+- ldub [%o1 - 1], %g2
+- stb %g2, [%o0 - 1]
+-1:
+- retl
+- RETL_INSN
+-
+-91: /* rshort_aligned_end */
+-
+- bne 75b
+- andcc %o2, 8, %g0
+-
+- be 1f
+- andcc %o2, 4, %g0
+-
+- ld [%o1 - 0x08], %g2
+- ld [%o1 - 0x04], %g3
+- sub %o1, 8, %o1
+- st %g2, [%o0 - 0x08]
+- st %g3, [%o0 - 0x04]
+- sub %o0, 8, %o0
+-1:
+- b 73b
+- mov %o2, %g1
+-
+-77: /* rnon_aligned */
+- cmp %o2, 15
+- bleu 75b
+- andcc %o0, 3, %g0
+- be 64f
+- andcc %o0, 1, %g0
+- be 63f
+- andcc %o0, 2, %g0
+- ldub [%o1 - 1], %g5
+- sub %o1, 1, %o1
+- stb %g5, [%o0 - 1]
+- sub %o0, 1, %o0
+- be 64f
+- sub %o2, 1, %o2
+-63:
+- ldub [%o1 - 1], %g5
+- sub %o1, 2, %o1
+- stb %g5, [%o0 - 1]
+- sub %o0, 2, %o0
+- ldub [%o1], %g5
+- sub %o2, 2, %o2
+- stb %g5, [%o0]
+-64:
+- and %o1, 3, %g2
+- and %o1, -4, %o1
+- and %o2, 0xc, %g3
+- add %o1, 4, %o1
+- cmp %g3, 4
+- sll %g2, 3, %g4
+- mov 32, %g2
+- be 4f
+- sub %g2, %g4, %g7
+-
+- blu 3f
+- cmp %g3, 8
+-
+- be 2f
+- srl %o2, 2, %g3
+-
+- ld [%o1 - 4], %o3
+- add %o0, -8, %o0
+- ld [%o1 - 8], %o4
+- add %o1, -16, %o1
+- b 7f
+- add %g3, 1, %g3
+-2:
+- ld [%o1 - 4], %o4
+- add %o0, -4, %o0
+- ld [%o1 - 8], %g1
+- add %o1, -12, %o1
+- b 8f
+- add %g3, 2, %g3
+-3:
+- ld [%o1 - 4], %o5
+- add %o0, -12, %o0
+- ld [%o1 - 8], %o3
+- add %o1, -20, %o1
+- b 6f
+- srl %o2, 2, %g3
+-4:
+- ld [%o1 - 4], %g1
+- srl %o2, 2, %g3
+- ld [%o1 - 8], %o5
+- add %o1, -24, %o1
+- add %o0, -16, %o0
+- add %g3, -1, %g3
+-
+- ld [%o1 + 12], %o3
+-5:
+- sll %o5, %g4, %g2
+- srl %g1, %g7, %g5
+- or %g2, %g5, %g2
+- st %g2, [%o0 + 12]
+-6:
+- ld [%o1 + 8], %o4
+- sll %o3, %g4, %g2
+- srl %o5, %g7, %g5
+- or %g2, %g5, %g2
+- st %g2, [%o0 + 8]
+-7:
+- ld [%o1 + 4], %g1
+- sll %o4, %g4, %g2
+- srl %o3, %g7, %g5
+- or %g2, %g5, %g2
+- st %g2, [%o0 + 4]
+-8:
+- ld [%o1], %o5
+- sll %g1, %g4, %g2
+- srl %o4, %g7, %g5
+- addcc %g3, -4, %g3
+- or %g2, %g5, %g2
+- add %o1, -16, %o1
+- st %g2, [%o0]
+- add %o0, -16, %o0
+- bne,a 5b
+- ld [%o1 + 12], %o3
+- sll %o5, %g4, %g2
+- srl %g1, %g7, %g5
+- srl %g4, 3, %g3
+- or %g2, %g5, %g2
+- add %o1, %g3, %o1
+- andcc %o2, 2, %g0
+- st %g2, [%o0 + 12]
+- be 1f
+- andcc %o2, 1, %g0
+-
+- ldub [%o1 + 15], %g5
+- add %o1, -2, %o1
+- stb %g5, [%o0 + 11]
+- add %o0, -2, %o0
+- ldub [%o1 + 16], %g5
+- stb %g5, [%o0 + 12]
+-1:
+- be 1f
+- nop
+- ldub [%o1 + 15], %g5
+- stb %g5, [%o0 + 11]
+-1:
+- retl
+- RETL_INSN
+-
+-#endif /* FASTER_REVERSE */
+-
+ /* NOTE: This code is executed just for the cases,
+ where %src (=%o1) & 3 is != 0.
+ We need to align it to 4. So, for (%src & 3)
+@@ -653,22 +319,6 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len
+ bne 82b
+ add %o0, 128, %o0
+
+-#ifndef FASTER_ALIGNED
+-
+- andcc %g1, 0x70, %g7
+- be 80b
+- andcc %g1, 8, %g0
+-
+- sethi %hi(80b), %o5
+- srl %g7, 1, %o4
+- add %g7, %o4, %o4
+- add %o1, %g7, %o1
+- sub %o5, %o4, %o5
+- jmpl %o5 + %lo(80b), %g0
+- add %o0, %g7, %o0
+-
+-#else /* FASTER_ALIGNED */
+-
+ andcc %g1, 0x70, %g7
+ be 84f
+ andcc %g1, 8, %g0
+@@ -723,19 +373,9 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len
+ retl
+ RETL_INSN
+
+-#endif /* FASTER_ALIGNED */
+-
+ 86: /* non_aligned */
+ cmp %o2, 6
+ bleu 88f
+-
+-#ifdef FASTER_NONALIGNED
+-
+- cmp %o2, 256
+- bcc 87f
+-
+-#endif /* FASTER_NONALIGNED */
+-
+ andcc %o0, 3, %g0
+ be 61f
+ andcc %o0, 1, %g0
+@@ -855,249 +495,6 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len
+ retl
+ RETL_INSN
+
+-#ifdef FASTER_NONALIGNED
+-
+-87: /* faster_nonaligned */
+-
+- andcc %o1, 3, %g0
+- be 3f
+- andcc %o1, 1, %g0
+-
+- be 4f
+- andcc %o1, 2, %g0
+-
+- ldub [%o1], %g2
+- add %o1, 1, %o1
+- stb %g2, [%o0]
+- sub %o2, 1, %o2
+- bne 3f
+- add %o0, 1, %o0
+-4:
+- lduh [%o1], %g2
+- add %o1, 2, %o1
+- srl %g2, 8, %g3
+- sub %o2, 2, %o2
+- stb %g3, [%o0]
+- add %o0, 2, %o0
+- stb %g2, [%o0 - 1]
+-3:
+- andcc %o1, 4, %g0
+-
+- bne 2f
+- cmp %o5, 1
+-
+- ld [%o1], %o4
+- srl %o4, 24, %g2
+- stb %g2, [%o0]
+- srl %o4, 16, %g3
+- stb %g3, [%o0 + 1]
+- srl %o4, 8, %g2
+- stb %g2, [%o0 + 2]
+- sub %o2, 4, %o2
+- stb %o4, [%o0 + 3]
+- add %o1, 4, %o1
+- add %o0, 4, %o0
+-2:
+- be 33f
+- cmp %o5, 2
+- be 32f
+- sub %o2, 4, %o2
+-31:
+- ld [%o1], %g2
+- add %o1, 4, %o1
+- srl %g2, 24, %g3
+- and %o0, 7, %g5
+- stb %g3, [%o0]
+- cmp %g5, 7
+- sll %g2, 8, %g1
+- add %o0, 4, %o0
+- be 41f
+- and %o2, 0xffffffc0, %o3
+- ld [%o0 - 7], %o4
+-4:
+- SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+- SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+- SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+- SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+- subcc %o3, 64, %o3
+- add %o1, 64, %o1
+- bne 4b
+- add %o0, 64, %o0
+-
+- andcc %o2, 0x30, %o3
+- be,a 1f
+- srl %g1, 16, %g2
+-4:
+- SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+- subcc %o3, 16, %o3
+- add %o1, 16, %o1
+- bne 4b
+- add %o0, 16, %o0
+-
+- srl %g1, 16, %g2
+-1:
+- st %o4, [%o0 - 7]
+- sth %g2, [%o0 - 3]
+- srl %g1, 8, %g4
+- b 88f
+- stb %g4, [%o0 - 1]
+-32:
+- ld [%o1], %g2
+- add %o1, 4, %o1
+- srl %g2, 16, %g3
+- and %o0, 7, %g5
+- sth %g3, [%o0]
+- cmp %g5, 6
+- sll %g2, 16, %g1
+- add %o0, 4, %o0
+- be 42f
+- and %o2, 0xffffffc0, %o3
+- ld [%o0 - 6], %o4
+-4:
+- SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+- SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+- SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+- SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+- subcc %o3, 64, %o3
+- add %o1, 64, %o1
+- bne 4b
+- add %o0, 64, %o0
+-
+- andcc %o2, 0x30, %o3
+- be,a 1f
+- srl %g1, 16, %g2
+-4:
+- SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+- subcc %o3, 16, %o3
+- add %o1, 16, %o1
+- bne 4b
+- add %o0, 16, %o0
+-
+- srl %g1, 16, %g2
+-1:
+- st %o4, [%o0 - 6]
+- b 88f
+- sth %g2, [%o0 - 2]
+-33:
+- ld [%o1], %g2
+- sub %o2, 4, %o2
+- srl %g2, 24, %g3
+- and %o0, 7, %g5
+- stb %g3, [%o0]
+- cmp %g5, 5
+- srl %g2, 8, %g4
+- sll %g2, 24, %g1
+- sth %g4, [%o0 + 1]
+- add %o1, 4, %o1
+- be 43f
+- and %o2, 0xffffffc0, %o3
+-
+- ld [%o0 - 1], %o4
+- add %o0, 4, %o0
+-4:
+- SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
+- SMOVE_CHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
+- SMOVE_CHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
+- SMOVE_CHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
+- subcc %o3, 64, %o3
+- add %o1, 64, %o1
+- bne 4b
+- add %o0, 64, %o0
+-
+- andcc %o2, 0x30, %o3
+- be,a 1f
+- srl %g1, 24, %g2
+-4:
+- SMOVE_CHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, -1)
+- subcc %o3, 16, %o3
+- add %o1, 16, %o1
+- bne 4b
+- add %o0, 16, %o0
+-
+- srl %g1, 24, %g2
+-1:
+- st %o4, [%o0 - 5]
+- b 88f
+- stb %g2, [%o0 - 1]
+-41:
+- SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+- SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+- SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+- SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+- subcc %o3, 64, %o3
+- add %o1, 64, %o1
+- bne 41b
+- add %o0, 64, %o0
+-
+- andcc %o2, 0x30, %o3
+- be,a 1f
+- srl %g1, 16, %g2
+-4:
+- SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 8, 24, -3)
+- subcc %o3, 16, %o3
+- add %o1, 16, %o1
+- bne 4b
+- add %o0, 16, %o0
+-
+- srl %g1, 16, %g2
+-1:
+- sth %g2, [%o0 - 3]
+- srl %g1, 8, %g4
+- b 88f
+- stb %g4, [%o0 - 1]
+-43:
+- SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
+- SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
+- SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
+- SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
+- subcc %o3, 64, %o3
+- add %o1, 64, %o1
+- bne 43b
+- add %o0, 64, %o0
+-
+- andcc %o2, 0x30, %o3
+- be,a 1f
+- srl %g1, 24, %g2
+-4:
+- SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 24, 8, 3)
+- subcc %o3, 16, %o3
+- add %o1, 16, %o1
+- bne 4b
+- add %o0, 16, %o0
+-
+- srl %g1, 24, %g2
+-1:
+- stb %g2, [%o0 + 3]
+- b 88f
+- add %o0, 4, %o0
+-42:
+- SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+- SMOVE_ALIGNCHUNK(o1, o0, 0x10, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+- SMOVE_ALIGNCHUNK(o1, o0, 0x20, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+- SMOVE_ALIGNCHUNK(o1, o0, 0x30, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+- subcc %o3, 64, %o3
+- add %o1, 64, %o1
+- bne 42b
+- add %o0, 64, %o0
+-
+- andcc %o2, 0x30, %o3
+- be,a 1f
+- srl %g1, 16, %g2
+-4:
+- SMOVE_ALIGNCHUNK(o1, o0, 0x00, g2, g3, g4, g5, o4, o5, g7, g1, 16, 16, -2)
+- subcc %o3, 16, %o3
+- add %o1, 16, %o1
+- bne 4b
+- add %o0, 16, %o0
+-
+- srl %g1, 16, %g2
+-1:
+- sth %g2, [%o0 - 2]
+-
+- /* Fall through */
+-
+-#endif /* FASTER_NONALIGNED */
+-
+ 88: /* short_end */
+
+ and %o2, 0xe, %o3
--- /dev/null
+From 2e5dbd43a1c674f1d82c22b8c4070172882024b8 Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Wed, 19 Oct 2011 15:30:14 -0700
+Subject: sparc32: Remove uses of %g7 in memcpy implementation.
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit 21f74d361dfd6a7d0e47574e315f780d8172084a ]
+
+This is setting things up so that we can correct the return
+value, so that it properly returns the original destination
+buffer pointer.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Tested-by: Kjetil Oftedal <oftedal@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/lib/memcpy.S | 177 ++++++++++++++++++++++++------------------------
+ 1 file changed, 91 insertions(+), 86 deletions(-)
+
+--- a/arch/sparc/lib/memcpy.S
++++ b/arch/sparc/lib/memcpy.S
+@@ -235,7 +235,7 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len
+ add %o1, 4, %o1
+ add %o0, 4, %o0
+ 2:
+- andcc %g1, 0xffffff80, %g7
++ andcc %g1, 0xffffff80, %g0
+ be 3f
+ andcc %o0, 4, %g0
+
+@@ -245,22 +245,23 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len
+ MOVE_BIGCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
+ MOVE_BIGCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
+ MOVE_BIGCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
+- subcc %g7, 128, %g7
++ sub %g1, 128, %g1
+ add %o1, 128, %o1
+- bne 5b
++ cmp %g1, 128
++ bge 5b
+ add %o0, 128, %o0
+ 3:
+- andcc %g1, 0x70, %g7
++ andcc %g1, 0x70, %g4
+ be 80f
+ andcc %g1, 8, %g0
+
+ sethi %hi(80f), %o5
+- srl %g7, 1, %o4
+- add %g7, %o4, %o4
+- add %o1, %g7, %o1
++ srl %g4, 1, %o4
++ add %g4, %o4, %o4
++ add %o1, %g4, %o1
+ sub %o5, %o4, %o5
+ jmpl %o5 + %lo(80f), %g0
+- add %o0, %g7, %o0
++ add %o0, %g4, %o0
+
+ 79: /* memcpy_table */
+
+@@ -314,20 +315,21 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len
+ MOVE_BIGALIGNCHUNK(o1, o0, 0x20, o2, o3, o4, o5, g2, g3, g4, g5)
+ MOVE_BIGALIGNCHUNK(o1, o0, 0x40, o2, o3, o4, o5, g2, g3, g4, g5)
+ MOVE_BIGALIGNCHUNK(o1, o0, 0x60, o2, o3, o4, o5, g2, g3, g4, g5)
+- subcc %g7, 128, %g7
++ subcc %g1, 128, %g1
+ add %o1, 128, %o1
+- bne 82b
++ cmp %g1, 128
++ bge 82b
+ add %o0, 128, %o0
+
+- andcc %g1, 0x70, %g7
++ andcc %g1, 0x70, %g4
+ be 84f
+ andcc %g1, 8, %g0
+
+ sethi %hi(84f), %o5
+- add %o1, %g7, %o1
+- sub %o5, %g7, %o5
++ add %o1, %g4, %o1
++ sub %o5, %g4, %o5
+ jmpl %o5 + %lo(84f), %g0
+- add %o0, %g7, %o0
++ add %o0, %g4, %o0
+
+ 83: /* amemcpy_table */
+
+@@ -376,124 +378,127 @@ FUNC(memcpy) /* %o0=dst %o1=src %o2=len
+ 86: /* non_aligned */
+ cmp %o2, 6
+ bleu 88f
+- andcc %o0, 3, %g0
++ nop
++
++ save %sp, -96, %sp
++ andcc %i0, 3, %g0
+ be 61f
+- andcc %o0, 1, %g0
++ andcc %i0, 1, %g0
+ be 60f
+- andcc %o0, 2, %g0
++ andcc %i0, 2, %g0
+
+- ldub [%o1], %g5
+- add %o1, 1, %o1
+- stb %g5, [%o0]
+- sub %o2, 1, %o2
++ ldub [%i1], %g5
++ add %i1, 1, %i1
++ stb %g5, [%i0]
++ sub %i2, 1, %i2
+ bne 61f
+- add %o0, 1, %o0
++ add %i0, 1, %i0
+ 60:
+- ldub [%o1], %g3
+- add %o1, 2, %o1
+- stb %g3, [%o0]
+- sub %o2, 2, %o2
+- ldub [%o1 - 1], %g3
+- add %o0, 2, %o0
+- stb %g3, [%o0 - 1]
++ ldub [%i1], %g3
++ add %i1, 2, %i1
++ stb %g3, [%i0]
++ sub %i2, 2, %i2
++ ldub [%i1 - 1], %g3
++ add %i0, 2, %i0
++ stb %g3, [%i0 - 1]
+ 61:
+- and %o1, 3, %g2
+- and %o2, 0xc, %g3
+- and %o1, -4, %o1
++ and %i1, 3, %g2
++ and %i2, 0xc, %g3
++ and %i1, -4, %i1
+ cmp %g3, 4
+ sll %g2, 3, %g4
+ mov 32, %g2
+ be 4f
+- sub %g2, %g4, %g7
++ sub %g2, %g4, %l0
+
+ blu 3f
+ cmp %g3, 0x8
+
+ be 2f
+- srl %o2, 2, %g3
++ srl %i2, 2, %g3
+
+- ld [%o1], %o3
+- add %o0, -8, %o0
+- ld [%o1 + 4], %o4
++ ld [%i1], %i3
++ add %i0, -8, %i0
++ ld [%i1 + 4], %i4
+ b 8f
+ add %g3, 1, %g3
+ 2:
+- ld [%o1], %o4
+- add %o0, -12, %o0
+- ld [%o1 + 4], %o5
++ ld [%i1], %i4
++ add %i0, -12, %i0
++ ld [%i1 + 4], %i5
+ add %g3, 2, %g3
+ b 9f
+- add %o1, -4, %o1
++ add %i1, -4, %i1
+ 3:
+- ld [%o1], %g1
+- add %o0, -4, %o0
+- ld [%o1 + 4], %o3
+- srl %o2, 2, %g3
++ ld [%i1], %g1
++ add %i0, -4, %i0
++ ld [%i1 + 4], %i3
++ srl %i2, 2, %g3
+ b 7f
+- add %o1, 4, %o1
++ add %i1, 4, %i1
+ 4:
+- ld [%o1], %o5
+- cmp %o2, 7
+- ld [%o1 + 4], %g1
+- srl %o2, 2, %g3
++ ld [%i1], %i5
++ cmp %i2, 7
++ ld [%i1 + 4], %g1
++ srl %i2, 2, %g3
+ bleu 10f
+- add %o1, 8, %o1
++ add %i1, 8, %i1
+
+- ld [%o1], %o3
++ ld [%i1], %i3
+ add %g3, -1, %g3
+ 5:
+- sll %o5, %g4, %g2
+- srl %g1, %g7, %g5
++ sll %i5, %g4, %g2
++ srl %g1, %l0, %g5
+ or %g2, %g5, %g2
+- st %g2, [%o0]
++ st %g2, [%i0]
+ 7:
+- ld [%o1 + 4], %o4
++ ld [%i1 + 4], %i4
+ sll %g1, %g4, %g2
+- srl %o3, %g7, %g5
++ srl %i3, %l0, %g5
+ or %g2, %g5, %g2
+- st %g2, [%o0 + 4]
++ st %g2, [%i0 + 4]
+ 8:
+- ld [%o1 + 8], %o5
+- sll %o3, %g4, %g2
+- srl %o4, %g7, %g5
++ ld [%i1 + 8], %i5
++ sll %i3, %g4, %g2
++ srl %i4, %l0, %g5
+ or %g2, %g5, %g2
+- st %g2, [%o0 + 8]
++ st %g2, [%i0 + 8]
+ 9:
+- ld [%o1 + 12], %g1
+- sll %o4, %g4, %g2
+- srl %o5, %g7, %g5
++ ld [%i1 + 12], %g1
++ sll %i4, %g4, %g2
++ srl %i5, %l0, %g5
+ addcc %g3, -4, %g3
+ or %g2, %g5, %g2
+- add %o1, 16, %o1
+- st %g2, [%o0 + 12]
+- add %o0, 16, %o0
++ add %i1, 16, %i1
++ st %g2, [%i0 + 12]
++ add %i0, 16, %i0
+ bne,a 5b
+- ld [%o1], %o3
++ ld [%i1], %i3
+ 10:
+- sll %o5, %g4, %g2
+- srl %g1, %g7, %g5
+- srl %g7, 3, %g3
++ sll %i5, %g4, %g2
++ srl %g1, %l0, %g5
++ srl %l0, 3, %g3
+ or %g2, %g5, %g2
+- sub %o1, %g3, %o1
+- andcc %o2, 2, %g0
+- st %g2, [%o0]
++ sub %i1, %g3, %i1
++ andcc %i2, 2, %g0
++ st %g2, [%i0]
+ be 1f
+- andcc %o2, 1, %g0
++ andcc %i2, 1, %g0
+
+- ldub [%o1], %g2
+- add %o1, 2, %o1
+- stb %g2, [%o0 + 4]
+- add %o0, 2, %o0
+- ldub [%o1 - 1], %g2
+- stb %g2, [%o0 + 3]
++ ldub [%i1], %g2
++ add %i1, 2, %i1
++ stb %g2, [%i0 + 4]
++ add %i0, 2, %i0
++ ldub [%i1 - 1], %g2
++ stb %g2, [%i0 + 3]
+ 1:
+ be 1f
+ nop
+- ldub [%o1], %g2
+- stb %g2, [%o0 + 4]
++ ldub [%i1], %g2
++ stb %g2, [%i0 + 4]
+ 1:
+- retl
+- RETL_INSN
++ ret
++ restore %g0, %g0, %o0
+
+ 88: /* short_end */
+
--- /dev/null
+From ff3f6f646f6eba78b05cc38af922782bd1b8712f Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Mon, 31 Oct 2011 01:05:49 -0700
+Subject: sparc64: Fix masking and shifting in VIS fpcmp emulation.
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit 2e8ecdc008a16b9a6c4b9628bb64d0d1c05f9f92 ]
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/kernel/visemul.c | 32 ++++++++++++++++----------------
+ 1 file changed, 16 insertions(+), 16 deletions(-)
+
+--- a/arch/sparc/kernel/visemul.c
++++ b/arch/sparc/kernel/visemul.c
+@@ -713,17 +713,17 @@ static void pcmp(struct pt_regs *regs, u
+ s16 b = (rs2 >> (i * 16)) & 0xffff;
+
+ if (a > b)
+- rd_val |= 1 << i;
++ rd_val |= 8 >> i;
+ }
+ break;
+
+ case FCMPGT32_OPF:
+ for (i = 0; i < 2; i++) {
+- s32 a = (rs1 >> (i * 32)) & 0xffff;
+- s32 b = (rs2 >> (i * 32)) & 0xffff;
++ s32 a = (rs1 >> (i * 32)) & 0xffffffff;
++ s32 b = (rs2 >> (i * 32)) & 0xffffffff;
+
+ if (a > b)
+- rd_val |= 1 << i;
++ rd_val |= 2 >> i;
+ }
+ break;
+
+@@ -733,17 +733,17 @@ static void pcmp(struct pt_regs *regs, u
+ s16 b = (rs2 >> (i * 16)) & 0xffff;
+
+ if (a <= b)
+- rd_val |= 1 << i;
++ rd_val |= 8 >> i;
+ }
+ break;
+
+ case FCMPLE32_OPF:
+ for (i = 0; i < 2; i++) {
+- s32 a = (rs1 >> (i * 32)) & 0xffff;
+- s32 b = (rs2 >> (i * 32)) & 0xffff;
++ s32 a = (rs1 >> (i * 32)) & 0xffffffff;
++ s32 b = (rs2 >> (i * 32)) & 0xffffffff;
+
+ if (a <= b)
+- rd_val |= 1 << i;
++ rd_val |= 2 >> i;
+ }
+ break;
+
+@@ -753,17 +753,17 @@ static void pcmp(struct pt_regs *regs, u
+ s16 b = (rs2 >> (i * 16)) & 0xffff;
+
+ if (a != b)
+- rd_val |= 1 << i;
++ rd_val |= 8 >> i;
+ }
+ break;
+
+ case FCMPNE32_OPF:
+ for (i = 0; i < 2; i++) {
+- s32 a = (rs1 >> (i * 32)) & 0xffff;
+- s32 b = (rs2 >> (i * 32)) & 0xffff;
++ s32 a = (rs1 >> (i * 32)) & 0xffffffff;
++ s32 b = (rs2 >> (i * 32)) & 0xffffffff;
+
+ if (a != b)
+- rd_val |= 1 << i;
++ rd_val |= 2 >> i;
+ }
+ break;
+
+@@ -773,17 +773,17 @@ static void pcmp(struct pt_regs *regs, u
+ s16 b = (rs2 >> (i * 16)) & 0xffff;
+
+ if (a == b)
+- rd_val |= 1 << i;
++ rd_val |= 8 >> i;
+ }
+ break;
+
+ case FCMPEQ32_OPF:
+ for (i = 0; i < 2; i++) {
+- s32 a = (rs1 >> (i * 32)) & 0xffff;
+- s32 b = (rs2 >> (i * 32)) & 0xffff;
++ s32 a = (rs1 >> (i * 32)) & 0xffffffff;
++ s32 b = (rs2 >> (i * 32)) & 0xffffffff;
+
+ if (a == b)
+- rd_val |= 1 << i;
++ rd_val |= 2 >> i;
+ }
+ break;
+ }
--- /dev/null
+From 485b01a81c3c41501c3b6c30e0899713a9bbb6a1 Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Thu, 22 Dec 2011 13:23:59 -0800
+Subject: sparc64: Fix MSIQ HV call ordering in pci_sun4v_msiq_build_irq().
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit 7cc8583372a21d98a23b703ad96cab03180b5030 ]
+
+This silently was working for many years and stopped working on
+Niagara-T3 machines.
+
+We need to set the MSIQ to VALID before we can set it's state to IDLE.
+
+On Niagara-T3, setting the state to IDLE first was causing HV_EINVAL
+errors. The hypervisor documentation says, rather ambiguously, that
+the MSIQ must be "initialized" before one can set the state.
+
+I previously understood this to mean merely that a successful setconf()
+operation has been performed on the MSIQ, which we have done at this
+point. But it seems to also mean that it has been set VALID too.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/kernel/pci_sun4v.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/sparc/kernel/pci_sun4v.c
++++ b/arch/sparc/kernel/pci_sun4v.c
+@@ -848,10 +848,10 @@ static int pci_sun4v_msiq_build_irq(stru
+ if (!irq)
+ return -ENOMEM;
+
+- if (pci_sun4v_msiq_setstate(pbm->devhandle, msiqid, HV_MSIQSTATE_IDLE))
+- return -EINVAL;
+ if (pci_sun4v_msiq_setvalid(pbm->devhandle, msiqid, HV_MSIQ_VALID))
+ return -EINVAL;
++ if (pci_sun4v_msiq_setstate(pbm->devhandle, msiqid, HV_MSIQSTATE_IDLE))
++ return -EINVAL;
+
+ return irq;
+ }
--- /dev/null
+From 0c84d92038fa2b130475b11044772c0b8f0e6f89 Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Thu, 17 Nov 2011 22:44:58 -0800
+Subject: sparc64: Patch sun4v code sequences properly on module load.
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit 0b64120cceb86e93cb1bda0dc055f13016646907 ]
+
+Some of the sun4v code patching occurs in inline functions visible
+to, and usable by, modules.
+
+Therefore we have to patch them up during module load.
+
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/sparc/kernel/entry.h | 7 ++++++
+ arch/sparc/kernel/module.c | 27 ++++++++++++++++++++++++
+ arch/sparc/kernel/setup_64.c | 48 +++++++++++++++++++++++++------------------
+ 3 files changed, 63 insertions(+), 19 deletions(-)
+
+--- a/arch/sparc/kernel/entry.h
++++ b/arch/sparc/kernel/entry.h
+@@ -42,6 +42,9 @@ extern void fpsave(unsigned long *fpregs
+ extern void fpload(unsigned long *fpregs, unsigned long *fsr);
+
+ #else /* CONFIG_SPARC32 */
++
++#include <asm/trap_block.h>
++
+ struct popc_3insn_patch_entry {
+ unsigned int addr;
+ unsigned int insns[3];
+@@ -57,6 +60,10 @@ extern struct popc_6insn_patch_entry __p
+ __popc_6insn_patch_end;
+
+ extern void __init per_cpu_patch(void);
++extern void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *,
++ struct sun4v_1insn_patch_entry *);
++extern void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *,
++ struct sun4v_2insn_patch_entry *);
+ extern void __init sun4v_patch(void);
+ extern void __init boot_cpu_id_too_large(int cpu);
+ extern unsigned int dcache_parity_tl1_occurred;
+--- a/arch/sparc/kernel/module.c
++++ b/arch/sparc/kernel/module.c
+@@ -17,6 +17,8 @@
+ #include <asm/processor.h>
+ #include <asm/spitfire.h>
+
++#include "entry.h"
++
+ #ifdef CONFIG_SPARC64
+
+ #include <linux/jump_label.h>
+@@ -220,6 +222,29 @@ int apply_relocate_add(Elf_Shdr *sechdrs
+ }
+
+ #ifdef CONFIG_SPARC64
++static void do_patch_sections(const Elf_Ehdr *hdr,
++ const Elf_Shdr *sechdrs)
++{
++ const Elf_Shdr *s, *sun4v_1insn = NULL, *sun4v_2insn = NULL;
++ char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
++
++ for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
++ if (!strcmp(".sun4v_1insn_patch", secstrings + s->sh_name))
++ sun4v_1insn = s;
++ if (!strcmp(".sun4v_2insn_patch", secstrings + s->sh_name))
++ sun4v_2insn = s;
++ }
++
++ if (sun4v_1insn && tlb_type == hypervisor) {
++ void *p = (void *) sun4v_1insn->sh_addr;
++ sun4v_patch_1insn_range(p, p + sun4v_1insn->sh_size);
++ }
++ if (sun4v_2insn && tlb_type == hypervisor) {
++ void *p = (void *) sun4v_2insn->sh_addr;
++ sun4v_patch_2insn_range(p, p + sun4v_2insn->sh_size);
++ }
++}
++
+ int module_finalize(const Elf_Ehdr *hdr,
+ const Elf_Shdr *sechdrs,
+ struct module *me)
+@@ -227,6 +252,8 @@ int module_finalize(const Elf_Ehdr *hdr,
+ /* make jump label nops */
+ jump_label_apply_nops(me);
+
++ do_patch_sections(hdr, sechdrs);
++
+ /* Cheetah's I-cache is fully coherent. */
+ if (tlb_type == spitfire) {
+ unsigned long va;
+--- a/arch/sparc/kernel/setup_64.c
++++ b/arch/sparc/kernel/setup_64.c
+@@ -234,40 +234,50 @@ void __init per_cpu_patch(void)
+ }
+ }
+
+-void __init sun4v_patch(void)
++void sun4v_patch_1insn_range(struct sun4v_1insn_patch_entry *start,
++ struct sun4v_1insn_patch_entry *end)
+ {
+- extern void sun4v_hvapi_init(void);
+- struct sun4v_1insn_patch_entry *p1;
+- struct sun4v_2insn_patch_entry *p2;
+-
+- if (tlb_type != hypervisor)
+- return;
++ while (start < end) {
++ unsigned long addr = start->addr;
+
+- p1 = &__sun4v_1insn_patch;
+- while (p1 < &__sun4v_1insn_patch_end) {
+- unsigned long addr = p1->addr;
+-
+- *(unsigned int *) (addr + 0) = p1->insn;
++ *(unsigned int *) (addr + 0) = start->insn;
+ wmb();
+ __asm__ __volatile__("flush %0" : : "r" (addr + 0));
+
+- p1++;
++ start++;
+ }
++}
+
+- p2 = &__sun4v_2insn_patch;
+- while (p2 < &__sun4v_2insn_patch_end) {
+- unsigned long addr = p2->addr;
++void sun4v_patch_2insn_range(struct sun4v_2insn_patch_entry *start,
++ struct sun4v_2insn_patch_entry *end)
++{
++ while (start < end) {
++ unsigned long addr = start->addr;
+
+- *(unsigned int *) (addr + 0) = p2->insns[0];
++ *(unsigned int *) (addr + 0) = start->insns[0];
+ wmb();
+ __asm__ __volatile__("flush %0" : : "r" (addr + 0));
+
+- *(unsigned int *) (addr + 4) = p2->insns[1];
++ *(unsigned int *) (addr + 4) = start->insns[1];
+ wmb();
+ __asm__ __volatile__("flush %0" : : "r" (addr + 4));
+
+- p2++;
++ start++;
+ }
++}
++
++void __init sun4v_patch(void)
++{
++ extern void sun4v_hvapi_init(void);
++
++ if (tlb_type != hypervisor)
++ return;
++
++ sun4v_patch_1insn_range(&__sun4v_1insn_patch,
++ &__sun4v_1insn_patch_end);
++
++ sun4v_patch_2insn_range(&__sun4v_2insn_patch,
++ &__sun4v_2insn_patch_end);
+
+ sun4v_hvapi_init();
+ }