summary refs log tree commit diff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-09 23:28:26 -0800
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-09 23:28:26 -0800
commitbfc1de0c40a26c6daa46c297e28138aecb4c5664 (patch)
tree5ac390e4c790076fda0644dd8b583ca819051905
parent1712a699ab32d4952fe6b0f97af91b8230bece98 (diff)
parente88bb41595ad67a8e7d5dd8c7bbeea2e66cc0cac (diff)
downloadlinux-bfc1de0c40a26c6daa46c297e28138aecb4c5664.tar.gz
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6: (24 commits)
  [SPARC]: Add solaris/sunos binary support to feature removal schedule.
  [SPARC]: Merge asm-sparc{,64}/a.out.h
  [SPARC]: Merge asm-sparc{,64}/fb.h
  [SPARC]: Merge asm-sparc{,64}/errno.h
  [SPARC]: Merge asm-sparc{,64}/emergency-restart.h
  [SPARC]: Merge asm-sparc{,64}/div64.h
  [SPARC]: Merge asm-sparc{,64}/device.h
  [SPARC]: Merge asm-sparc{,64}/current.h
  [SPARC]: Merge asm-sparc{,64}/cputime.h
  [SPARC]: Merge asm-sparc{,64}/cache.h
  [SPARC]: Merge asm-sparc{,64}/byteorder.h
  [SPARC]: Merge asm-sparc{,64}/bugs.h
  [SPARC]: Merge asm-sparc{,64}/bug.h
  [SPARC]: Kill BSD errno translation table and header files.
  [SPARC]: Merge asm-sparc{,64}/bpp.h
  [SPARC]: Merge include/asm-sparc{,64}/auxvec.h
  [SPARC]: Merge include/asm-sparc{,64}/of_device.h
  [SPARC]: Merge include/asm-sparc{,64}/prom.h
  [SPARC]: Remove of_platform_device_create
  [SPARC64]: Add kretprobe support.
  ...
-rw-r--r--Documentation/feature-removal-schedule.txt11
-rw-r--r--arch/sparc/kernel/errtbls.c144
-rw-r--r--arch/sparc/kernel/of_device.c27
-rw-r--r--arch/sparc/kernel/vmlinux.lds.S4
-rw-r--r--arch/sparc64/Kconfig4
-rw-r--r--arch/sparc64/kernel/iommu.c352
-rw-r--r--arch/sparc64/kernel/iommu_common.h33
-rw-r--r--arch/sparc64/kernel/kprobes.c113
-rw-r--r--arch/sparc64/kernel/of_device.c26
-rw-r--r--arch/sparc64/kernel/pci_sun4v.c278
-rw-r--r--include/asm-sparc/a.out.h31
-rw-r--r--include/asm-sparc/bpp.h2
-rw-r--r--include/asm-sparc/bsderrno.h94
-rw-r--r--include/asm-sparc/bug.h18
-rw-r--r--include/asm-sparc/bugs.h18
-rw-r--r--include/asm-sparc/byteorder.h51
-rw-r--r--include/asm-sparc/cache.h21
-rw-r--r--include/asm-sparc/current.h31
-rw-r--r--include/asm-sparc/device.h2
-rw-r--r--include/asm-sparc/errno.h1
-rw-r--r--include/asm-sparc/fb.h16
-rw-r--r--include/asm-sparc/of_platform.h5
-rw-r--r--include/asm-sparc/prom.h11
-rw-r--r--include/asm-sparc64/a.out.h99
-rw-r--r--include/asm-sparc64/auxvec.h5
-rw-r--r--include/asm-sparc64/bpp.h74
-rw-r--r--include/asm-sparc64/bsderrno.h94
-rw-r--r--include/asm-sparc64/bug.h23
-rw-r--r--include/asm-sparc64/bugs.h11
-rw-r--r--include/asm-sparc64/byteorder.h50
-rw-r--r--include/asm-sparc64/cache.h19
-rw-r--r--include/asm-sparc64/cputime.h7
-rw-r--r--include/asm-sparc64/current.h9
-rw-r--r--include/asm-sparc64/device.h22
-rw-r--r--include/asm-sparc64/div64.h2
-rw-r--r--include/asm-sparc64/emergency-restart.h7
-rw-r--r--include/asm-sparc64/errno.h115
-rw-r--r--include/asm-sparc64/fb.h28
-rw-r--r--include/asm-sparc64/io.h2
-rw-r--r--include/asm-sparc64/iommu.h1
-rw-r--r--include/asm-sparc64/kprobes.h4
-rw-r--r--include/asm-sparc64/of_device.h39
-rw-r--r--include/asm-sparc64/of_platform.h5
-rw-r--r--include/asm-sparc64/prom.h104
44 files changed, 689 insertions, 1324 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index ce9503c892b5..2039f47f2e65 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -304,3 +304,14 @@ Why:	The support code for the old firmware hurts code readability/maintainabilit
 	and slightly hurts runtime performance. Bugfixes for the old firmware
 	are not provided by Broadcom anymore.
 Who:	Michael Buesch <mb@bu3sch.de>
+
+---------------------------
+
+What:	Solaris/SunOS syscall and binary support on Sparc
+When:	2.6.26
+Why:	Largely unmaintained and almost entirely unused.  File system
+	layering used to divert library and dynamic linker searches to
+	/usr/gnemul is extremely buggy and unfixable.  Making it work
+	is largely pointless as without a lot of work only the most
+	trivial of Solaris binaries can work with the emulation code.
+Who:	David S. Miller <davem@davemloft.net>
diff --git a/arch/sparc/kernel/errtbls.c b/arch/sparc/kernel/errtbls.c
index bb36f6eadfee..ed14df7116e9 100644
--- a/arch/sparc/kernel/errtbls.c
+++ b/arch/sparc/kernel/errtbls.c
@@ -1,21 +1,18 @@
-/* $Id: errtbls.c,v 1.2 1995/11/25 00:57:55 davem Exp $
- * errtbls.c: Error number conversion tables between various syscall
- *            OS semantics.
+/* errtbls.c: Error number conversion tables.
  *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net)
  *
  * Based upon preliminary work which is:
  *
  * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
  */
 
-#include <asm/bsderrno.h>        /* NetBSD (bsd4.4) errnos */
 #include <asm/solerrno.h>        /* Solaris errnos */
 
-/* Here are tables which convert between Linux/SunOS error number
- * values to the equivalent in other OSs.  Note that since the Linux
- * ones have been set up to match exactly those of SunOS, no
- * translation table is needed for that OS.
+/* Here is the table which converts between Linux error number values
+ * to the equivalent under Solaris.  Note that since the Linux ones
+ * have been set up to match exactly those of SunOS, no translation
+ * table is needed for that OS.
  */
 
 int solaris_errno[] = {
@@ -145,132 +142,3 @@ int solaris_errno[] = {
 	SOL_ELIBMAX,
 	SOL_ELIBSCN,
 };
-
-int netbsd_errno[] = {
-	0,
-	BSD_EPERM,
-	BSD_ENOENT,
-	BSD_ESRCH,
-	BSD_EINTR,
-	BSD_EIO,
-	BSD_ENXIO,
-	BSD_E2BIG,
-	BSD_ENOEXEC,
-	BSD_EBADF,
-	BSD_ECHILD,
-	BSD_EAGAIN,
-	BSD_ENOMEM,
-	BSD_EACCES,
-	BSD_EFAULT,
-	BSD_NOTBLK,
-	BSD_EBUSY,
-	BSD_EEXIST,
-	BSD_EXDEV,
-	BSD_ENODEV,
-	BSD_ENOTDIR,
-	BSD_EISDIR,
-	BSD_EINVAL,
-	BSD_ENFILE,
-	BSD_EMFILE,
-	BSD_ENOTTY,
-	BSD_ETXTBSY,
-	BSD_EFBIG,
-	BSD_ENOSPC,
-	BSD_ESPIPE,
-	BSD_EROFS,
-	BSD_EMLINK,
-	BSD_EPIPE,
-	BSD_EDOM,
-	BSD_ERANGE,
-	BSD_EWOULDBLOCK,
-	BSD_EINPROGRESS,
-	BSD_EALREADY,
-	BSD_ENOTSOCK,
-	BSD_EDESTADDRREQ,
-	BSD_EMSGSIZE,
-	BSD_EPROTOTYPE,
-	BSD_ENOPROTOOPT,
-	BSD_EPROTONOSUPPORT,
-	BSD_ESOCKTNOSUPPORT,
-	BSD_EOPNOTSUPP,
-	BSD_EPFNOSUPPORT,
-	BSD_EAFNOSUPPORT,
-	BSD_EADDRINUSE,
-	BSD_EADDRNOTAVAIL,
-	BSD_ENETDOWN,
-	BSD_ENETUNREACH,
-	BSD_ENETRESET,
-	BSD_ECONNABORTED,
-	BSD_ECONNRESET,
-	BSD_ENOBUFS,
-	BSD_EISCONN,
-	BSD_ENOTONN,
-	BSD_ESHUTDOWN,
-	BSD_ETOOMANYREFS,
-	BSD_ETIMEDOUT,
-	BSD_ECONNREFUSED,
-	BSD_ELOOP,
-	BSD_ENAMETOOLONG,
-	BSD_EHOSTDOWN,
-	BSD_EHOSTUNREACH,
-	BSD_ENOTEMPTY,
-	BSD_EPROCLIM,
-	BSD_EUSERS,
-	BSD_EDQUOT,
-	BSD_ESTALE,
-	BSD_EREMOTE,
-	BSD_ENOSTR,
-	BSD_ETIME,
-	BSD_ENOSR,
-	BSD_ENOMSG,
-	BSD_EBADMSG,
-	BSD_IDRM,
-	BSD_EDEADLK,
-	BSD_ENOLCK,
-	BSD_ENONET,
-	BSD_ERREMOTE,
-	BSD_ENOLINK,
-	BSD_EADV,
-	BSD_ESRMNT,
-	BSD_ECOMM,
-	BSD_EPROTO,
-	BSD_EMULTIHOP,
-	BSD_EINVAL,    /* EDOTDOT XXX??? */
-	BSD_REMCHG,
-	BSD_NOSYS,
-	BSD_STRPIPE,
-	BSD_EOVERFLOW,
-	BSD_EBADFD,
-	BSD_ECHRNG,
-	BSD_EL2NSYNC,
-	BSD_EL3HLT,
-	BSD_EL3RST,
-	BSD_NRNG,
-	BSD_EUNATCH,
-	BSD_ENOCSI,
-	BSD_EL2HLT,
-	BSD_EBADE,
-	BSD_EBADR,
-	BSD_EXFULL,
-	BSD_ENOANO,
-	BSD_EBADRQC,
-	BSD_EBADSLT,
-	BSD_EDEADLOCK,
-	BSD_EBFONT,
-	BSD_ELIBEXEC,
-	BSD_ENODATA,
-	BSD_ELIBBAD,
-	BSD_ENOPKG,
-	BSD_ELIBACC,
-	BSD_ENOTUNIQ,
-	BSD_ERESTART,
-	BSD_EUCLEAN,
-	BSD_ENOTNAM,
-	BSD_ENAVAIL,
-	BSD_EISNAM,
-	BSD_EREMOTEIO,
-	BSD_EILSEQ,
-	BSD_ELIBMAX,
-	BSD_ELIBSCN,
-};
-
diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c
index 3ea000d15e3a..cc4c235c4f59 100644
--- a/arch/sparc/kernel/of_device.c
+++ b/arch/sparc/kernel/of_device.c
@@ -584,30 +584,3 @@ static int __init of_debug(char *str)
 }
 
 __setup("of_debug=", of_debug);
-
-struct of_device* of_platform_device_create(struct device_node *np,
-					    const char *bus_id,
-					    struct device *parent,
-					    struct bus_type *bus)
-{
-	struct of_device *dev;
-
-	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-	if (!dev)
-		return NULL;
-
-	dev->dev.parent = parent;
-	dev->dev.bus = bus;
-	dev->dev.release = of_release_dev;
-
-	strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
-
-	if (of_device_register(dev) != 0) {
-		kfree(dev);
-		return NULL;
-	}
-
-	return dev;
-}
-
-EXPORT_SYMBOL(of_platform_device_create);
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index 216147d6e61f..b1002c607196 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -89,6 +89,10 @@ SECTIONS
 	.data.cacheline_aligned : {
 		*(.data.cacheline_aligned)
 	}
+	. = ALIGN(32);
+	.data.read_mostly : {
+		*(.data.read_mostly)
+	}
 
 	__bss_start = .;
 	.sbss : {
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig
index 810755637311..3af378ddb6ae 100644
--- a/arch/sparc64/Kconfig
+++ b/arch/sparc64/Kconfig
@@ -41,6 +41,10 @@ config MMU
 	bool
 	default y
 
+config IOMMU_HELPER
+	bool
+	default y
+
 config QUICKLIST
 	bool
 	default y
diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c
index 5623a4d59dff..d3276ebcfb47 100644
--- a/arch/sparc64/kernel/iommu.c
+++ b/arch/sparc64/kernel/iommu.c
@@ -1,6 +1,6 @@
 /* iommu.c: Generic sparc64 IOMMU support.
  *
- * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 1999, 2007, 2008 David S. Miller (davem@davemloft.net)
  * Copyright (C) 1999, 2000 Jakub Jelinek (jakub@redhat.com)
  */
 
@@ -10,6 +10,7 @@
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <linux/errno.h>
+#include <linux/iommu-helper.h>
 
 #ifdef CONFIG_PCI
 #include <linux/pci.h>
@@ -41,7 +42,7 @@
 			       "i" (ASI_PHYS_BYPASS_EC_E))
 
 /* Must be invoked under the IOMMU lock. */
-static void __iommu_flushall(struct iommu *iommu)
+static void iommu_flushall(struct iommu *iommu)
 {
 	if (iommu->iommu_flushinv) {
 		iommu_write(iommu->iommu_flushinv, ~(u64)0);
@@ -83,54 +84,91 @@ static inline void iopte_make_dummy(struct iommu *iommu, iopte_t *iopte)
 	iopte_val(*iopte) = val;
 }
 
-/* Based largely upon the ppc64 iommu allocator.  */
-static long arena_alloc(struct iommu *iommu, unsigned long npages)
+/* Based almost entirely upon the ppc64 iommu allocator.  If you use the 'handle'
+ * facility it must all be done in one pass while under the iommu lock.
+ *
+ * On sun4u platforms, we only flush the IOMMU once every time we've passed
+ * over the entire page table doing allocations.  Therefore we only ever advance
+ * the hint and cannot backtrack it.
+ */
+unsigned long iommu_range_alloc(struct device *dev,
+				struct iommu *iommu,
+				unsigned long npages,
+				unsigned long *handle)
 {
+	unsigned long n, end, start, limit, boundary_size;
 	struct iommu_arena *arena = &iommu->arena;
-	unsigned long n, i, start, end, limit;
-	int pass;
+	int pass = 0;
+
+	/* This allocator was derived from x86_64's bit string search */
+
+	/* Sanity check */
+	if (unlikely(npages == 0)) {
+		if (printk_ratelimit())
+			WARN_ON(1);
+		return DMA_ERROR_CODE;
+	}
+
+	if (handle && *handle)
+		start = *handle;
+	else
+		start = arena->hint;
 
 	limit = arena->limit;
-	start = arena->hint;
-	pass = 0;
 
-again:
-	n = find_next_zero_bit(arena->map, limit, start);
-	end = n + npages;
-	if (unlikely(end >= limit)) {
+	/* The case below can happen if we have a small segment appended
+	 * to a large, or when the previous alloc was at the very end of
+	 * the available space. If so, go back to the beginning and flush.
+	 */
+	if (start >= limit) {
+		start = 0;
+		if (iommu->flush_all)
+			iommu->flush_all(iommu);
+	}
+
+ again:
+
+	if (dev)
+		boundary_size = ALIGN(dma_get_seg_boundary(dev) + 1,
+				      1 << IO_PAGE_SHIFT);
+	else
+		boundary_size = ALIGN(1UL << 32, 1 << IO_PAGE_SHIFT);
+
+	n = iommu_area_alloc(arena->map, limit, start, npages, 0,
+			     boundary_size >> IO_PAGE_SHIFT, 0);
+	if (n == -1) {
 		if (likely(pass < 1)) {
-			limit = start;
+			/* First failure, rescan from the beginning.  */
 			start = 0;
-			__iommu_flushall(iommu);
+			if (iommu->flush_all)
+				iommu->flush_all(iommu);
 			pass++;
 			goto again;
 		} else {
-			/* Scanned the whole thing, give up. */
-			return -1;
-		}
-	}
-
-	for (i = n; i < end; i++) {
-		if (test_bit(i, arena->map)) {
-			start = i + 1;
-			goto again;
+			/* Second failure, give up */
+			return DMA_ERROR_CODE;
 		}
 	}
 
-	for (i = n; i < end; i++)
-		__set_bit(i, arena->map);
+	end = n + npages;
 
 	arena->hint = end;
 
+	/* Update handle for SG allocations */
+	if (handle)
+		*handle = end;
+
 	return n;
 }
 
-static void arena_free(struct iommu_arena *arena, unsigned long base, unsigned long npages)
+void iommu_range_free(struct iommu *iommu, dma_addr_t dma_addr, unsigned long npages)
 {
-	unsigned long i;
+	struct iommu_arena *arena = &iommu->arena;
+	unsigned long entry;
 
-	for (i = base; i < (base + npages); i++)
-		__clear_bit(i, arena->map);
+	entry = (dma_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT;
+
+	iommu_area_free(arena->map, entry, npages);
 }
 
 int iommu_table_init(struct iommu *iommu, int tsbsize,
@@ -156,6 +194,9 @@ int iommu_table_init(struct iommu *iommu, int tsbsize,
 	}
 	iommu->arena.limit = num_tsb_entries;
 
+	if (tlb_type != hypervisor)
+		iommu->flush_all = iommu_flushall;
+
 	/* Allocate and initialize the dummy page which we
 	 * set inactive IO PTEs to point to.
 	 */
@@ -192,22 +233,18 @@ out_free_map:
 	return -ENOMEM;
 }
 
-static inline iopte_t *alloc_npages(struct iommu *iommu, unsigned long npages)
+static inline iopte_t *alloc_npages(struct device *dev, struct iommu *iommu,
+				    unsigned long npages)
 {
-	long entry;
+	unsigned long entry;
 
-	entry = arena_alloc(iommu, npages);
-	if (unlikely(entry < 0))
+	entry = iommu_range_alloc(dev, iommu, npages, NULL);
+	if (unlikely(entry == DMA_ERROR_CODE))
 		return NULL;
 
 	return iommu->page_table + entry;
 }
 
-static inline void free_npages(struct iommu *iommu, dma_addr_t base, unsigned long npages)
-{
-	arena_free(&iommu->arena, base >> IO_PAGE_SHIFT, npages);
-}
-
 static int iommu_alloc_ctx(struct iommu *iommu)
 {
 	int lowest = iommu->ctx_lowest_free;
@@ -258,7 +295,7 @@ static void *dma_4u_alloc_coherent(struct device *dev, size_t size,
 	iommu = dev->archdata.iommu;
 
 	spin_lock_irqsave(&iommu->lock, flags);
-	iopte = alloc_npages(iommu, size >> IO_PAGE_SHIFT);
+	iopte = alloc_npages(dev, iommu, size >> IO_PAGE_SHIFT);
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
 	if (unlikely(iopte == NULL)) {
@@ -296,7 +333,7 @@ static void dma_4u_free_coherent(struct device *dev, size_t size,
 
 	spin_lock_irqsave(&iommu->lock, flags);
 
-	free_npages(iommu, dvma - iommu->page_table_map_base, npages);
+	iommu_range_free(iommu, dvma, npages);
 
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
@@ -327,7 +364,7 @@ static dma_addr_t dma_4u_map_single(struct device *dev, void *ptr, size_t sz,
 	npages >>= IO_PAGE_SHIFT;
 
 	spin_lock_irqsave(&iommu->lock, flags);
-	base = alloc_npages(iommu, npages);
+	base = alloc_npages(dev, iommu, npages);
 	ctx = 0;
 	if (iommu->iommu_ctxflush)
 		ctx = iommu_alloc_ctx(iommu);
@@ -465,7 +502,7 @@ static void dma_4u_unmap_single(struct device *dev, dma_addr_t bus_addr,
 	for (i = 0; i < npages; i++)
 		iopte_make_dummy(iommu, base + i);
 
-	free_npages(iommu, bus_addr - iommu->page_table_map_base, npages);
+	iommu_range_free(iommu, bus_addr, npages);
 
 	iommu_free_ctx(iommu, ctx);
 
@@ -475,124 +512,209 @@ static void dma_4u_unmap_single(struct device *dev, dma_addr_t bus_addr,
 static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
 			 int nelems, enum dma_data_direction direction)
 {
-	unsigned long flags, ctx, i, npages, iopte_protection;
-	struct scatterlist *sg;
+	struct scatterlist *s, *outs, *segstart;
+	unsigned long flags, handle, prot, ctx;
+	dma_addr_t dma_next = 0, dma_addr;
+	unsigned int max_seg_size;
+	int outcount, incount, i;
 	struct strbuf *strbuf;
 	struct iommu *iommu;
-	iopte_t *base;
-	u32 dma_base;
-
-	/* Fast path single entry scatterlists. */
-	if (nelems == 1) {
-		sglist->dma_address =
-			dma_4u_map_single(dev, sg_virt(sglist),
-					  sglist->length, direction);
-		if (unlikely(sglist->dma_address == DMA_ERROR_CODE))
-			return 0;
-		sglist->dma_length = sglist->length;
-		return 1;
-	}
+
+	BUG_ON(direction == DMA_NONE);
 
 	iommu = dev->archdata.iommu;
 	strbuf = dev->archdata.stc;
-
-	if (unlikely(direction == DMA_NONE))
-		goto bad_no_ctx;
-
-	npages = calc_npages(sglist, nelems);
+	if (nelems == 0 || !iommu)
+		return 0;
 
 	spin_lock_irqsave(&iommu->lock, flags);
 
-	base = alloc_npages(iommu, npages);
 	ctx = 0;
 	if (iommu->iommu_ctxflush)
 		ctx = iommu_alloc_ctx(iommu);
 
-	spin_unlock_irqrestore(&iommu->lock, flags);
-
-	if (base == NULL)
-		goto bad;
-
-	dma_base = iommu->page_table_map_base +
-		((base - iommu->page_table) << IO_PAGE_SHIFT);
-
 	if (strbuf->strbuf_enabled)
-		iopte_protection = IOPTE_STREAMING(ctx);
+		prot = IOPTE_STREAMING(ctx);
 	else
-		iopte_protection = IOPTE_CONSISTENT(ctx);
+		prot = IOPTE_CONSISTENT(ctx);
 	if (direction != DMA_TO_DEVICE)
-		iopte_protection |= IOPTE_WRITE;
-
-	for_each_sg(sglist, sg, nelems, i) {
-		unsigned long paddr = SG_ENT_PHYS_ADDRESS(sg);
-		unsigned long slen = sg->length;
-		unsigned long this_npages;
+		prot |= IOPTE_WRITE;
+
+	outs = s = segstart = &sglist[0];
+	outcount = 1;
+	incount = nelems;
+	handle = 0;
+
+	/* Init first segment length for backout at failure */
+	outs->dma_length = 0;
+
+	max_seg_size = dma_get_max_seg_size(dev);
+	for_each_sg(sglist, s, nelems, i) {
+		unsigned long paddr, npages, entry, slen;
+		iopte_t *base;
+
+		slen = s->length;
+		/* Sanity check */
+		if (slen == 0) {
+			dma_next = 0;
+			continue;
+		}
+		/* Allocate iommu entries for that segment */
+		paddr = (unsigned long) SG_ENT_PHYS_ADDRESS(s);
+		npages = iommu_num_pages(paddr, slen);
+		entry = iommu_range_alloc(dev, iommu, npages, &handle);
+
+		/* Handle failure */
+		if (unlikely(entry == DMA_ERROR_CODE)) {
+			if (printk_ratelimit())
+				printk(KERN_INFO "iommu_alloc failed, iommu %p paddr %lx"
+				       " npages %lx\n", iommu, paddr, npages);
+			goto iommu_map_failed;
+		}
 
-		this_npages = iommu_num_pages(paddr, slen);
+		base = iommu->page_table + entry;
 
-		sg->dma_address = dma_base | (paddr & ~IO_PAGE_MASK);
-		sg->dma_length = slen;
+		/* Convert entry to a dma_addr_t */
+		dma_addr = iommu->page_table_map_base +
+			(entry << IO_PAGE_SHIFT);
+		dma_addr |= (s->offset & ~IO_PAGE_MASK);
 
+		/* Insert into HW table */
 		paddr &= IO_PAGE_MASK;
-		while (this_npages--) {
-			iopte_val(*base) = iopte_protection | paddr;
-
+		while (npages--) {
+			iopte_val(*base) = prot | paddr;
 			base++;
 			paddr += IO_PAGE_SIZE;
-			dma_base += IO_PAGE_SIZE;
 		}
+
+		/* If we are in an open segment, try merging */
+		if (segstart != s) {
+			/* We cannot merge if:
+			 * - allocated dma_addr isn't contiguous to previous allocation
+			 */
+			if ((dma_addr != dma_next) ||
+			    (outs->dma_length + s->length > max_seg_size)) {
+				/* Can't merge: create a new segment */
+				segstart = s;
+				outcount++;
+				outs = sg_next(outs);
+			} else {
+				outs->dma_length += s->length;
+			}
+		}
+
+		if (segstart == s) {
+			/* This is a new segment, fill entries */
+			outs->dma_address = dma_addr;
+			outs->dma_length = slen;
+		}
+
+		/* Calculate next page pointer for contiguous check */
+		dma_next = dma_addr + slen;
 	}
 
-	return nelems;
+	spin_unlock_irqrestore(&iommu->lock, flags);
+
+	if (outcount < incount) {
+		outs = sg_next(outs);
+		outs->dma_address = DMA_ERROR_CODE;
+		outs->dma_length = 0;
+	}
+
+	return outcount;
+
+iommu_map_failed:
+	for_each_sg(sglist, s, nelems, i) {
+		if (s->dma_length != 0) {
+			unsigned long vaddr, npages, entry, i;
+			iopte_t *base;
+
+			vaddr = s->dma_address & IO_PAGE_MASK;
+			npages = iommu_num_pages(s->dma_address, s->dma_length);
+			iommu_range_free(iommu, vaddr, npages);
+
+			entry = (vaddr - iommu->page_table_map_base)
+				>> IO_PAGE_SHIFT;
+			base = iommu->page_table + entry;
+
+			for (i = 0; i < npages; i++)
+				iopte_make_dummy(iommu, base + i);
+
+			s->dma_address = DMA_ERROR_CODE;
+			s->dma_length = 0;
+		}
+		if (s == outs)
+			break;
+	}
+	spin_unlock_irqrestore(&iommu->lock, flags);
 
-bad:
-	iommu_free_ctx(iommu, ctx);
-bad_no_ctx:
-	if (printk_ratelimit())
-		WARN_ON(1);
 	return 0;
 }
 
+/* If contexts are being used, they are the same in all of the mappings
+ * we make for a particular SG.
+ */
+static unsigned long fetch_sg_ctx(struct iommu *iommu, struct scatterlist *sg)
+{
+	unsigned long ctx = 0;
+
+	if (iommu->iommu_ctxflush) {
+		iopte_t *base;
+		u32 bus_addr;
+
+		bus_addr = sg->dma_address & IO_PAGE_MASK;
+		base = iommu->page_table +
+			((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
+
+		ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
+	}
+	return ctx;
+}
+
 static void dma_4u_unmap_sg(struct device *dev, struct scatterlist *sglist,
 			    int nelems, enum dma_data_direction direction)
 {
-	unsigned long flags, ctx, i, npages;
+	unsigned long flags, ctx;
+	struct scatterlist *sg;
 	struct strbuf *strbuf;
 	struct iommu *iommu;
-	iopte_t *base;
-	u32 bus_addr;
 
-	if (unlikely(direction == DMA_NONE)) {
-		if (printk_ratelimit())
-			WARN_ON(1);
-	}
+	BUG_ON(direction == DMA_NONE);
 
 	iommu = dev->archdata.iommu;
 	strbuf = dev->archdata.stc;
 
-	bus_addr = sglist->dma_address & IO_PAGE_MASK;
+	ctx = fetch_sg_ctx(iommu, sglist);
 
-	npages = calc_npages(sglist, nelems);
+	spin_lock_irqsave(&iommu->lock, flags);
 
-	base = iommu->page_table +
-		((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
+	sg = sglist;
+	while (nelems--) {
+		dma_addr_t dma_handle = sg->dma_address;
+		unsigned int len = sg->dma_length;
+		unsigned long npages, entry;
+		iopte_t *base;
+		int i;
 
-	spin_lock_irqsave(&iommu->lock, flags);
+		if (!len)
+			break;
+		npages = iommu_num_pages(dma_handle, len);
+		iommu_range_free(iommu, dma_handle, npages);
 
-	/* Record the context, if any. */
-	ctx = 0;
-	if (iommu->iommu_ctxflush)
-		ctx = (iopte_val(*base) & IOPTE_CONTEXT) >> 47UL;
+		entry = ((dma_handle - iommu->page_table_map_base)
+			 >> IO_PAGE_SHIFT);
+		base = iommu->page_table + entry;
 
-	/* Step 1: Kick data out of streaming buffers if necessary. */
-	if (strbuf->strbuf_enabled)
-		strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
+		dma_handle &= IO_PAGE_MASK;
+		if (strbuf->strbuf_enabled)
+			strbuf_flush(strbuf, iommu, dma_handle, ctx,
+				     npages, direction);
 
-	/* Step 2: Clear out the TSB entries. */
-	for (i = 0; i < npages; i++)
-		iopte_make_dummy(iommu, base + i);
+		for (i = 0; i < npages; i++)
+			iopte_make_dummy(iommu, base + i);
 
-	free_npages(iommu, bus_addr - iommu->page_table_map_base, npages);
+		sg = sg_next(sg);
+	}
 
 	iommu_free_ctx(iommu, ctx);
 
diff --git a/arch/sparc64/kernel/iommu_common.h b/arch/sparc64/kernel/iommu_common.h
index 4b5cafa2877a..0713bd58499c 100644
--- a/arch/sparc64/kernel/iommu_common.h
+++ b/arch/sparc64/kernel/iommu_common.h
@@ -1,9 +1,11 @@
-/* $Id: iommu_common.h,v 1.5 2001/12/11 09:41:01 davem Exp $
- * iommu_common.h: UltraSparc SBUS/PCI common iommu declarations.
+/* iommu_common.h: UltraSparc SBUS/PCI common iommu declarations.
  *
- * Copyright (C) 1999 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1999, 2008 David S. Miller (davem@davemloft.net)
  */
 
+#ifndef _IOMMU_COMMON_H
+#define _IOMMU_COMMON_H
+
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/sched.h>
@@ -56,21 +58,12 @@ static inline unsigned long calc_npages(struct scatterlist *sglist, int nelems)
 	return npages;
 }
 
-/* You are _strongly_ advised to enable the following debugging code
- * any time you make changes to the sg code below, run it for a while
- * with filesystems mounted read-only before buying the farm... -DaveM
- */
-#undef VERIFY_SG
-
-#ifdef VERIFY_SG
-extern void verify_sglist(struct scatterlist *sg, int nents, iopte_t *iopte, int npages);
-#endif
-
-/* Two addresses are "virtually contiguous" if and only if:
- * 1) They are equal, or...
- * 2) They are both on a page boundary
- */
-#define VCONTIG(__X, __Y)	(((__X) == (__Y)) || \
-				 (((__X) | (__Y)) << (64UL - PAGE_SHIFT)) == 0UL)
+extern unsigned long iommu_range_alloc(struct device *dev,
+				       struct iommu *iommu,
+				       unsigned long npages,
+				       unsigned long *handle);
+extern void iommu_range_free(struct iommu *iommu,
+			     dma_addr_t dma_addr,
+			     unsigned long npages);
 
-extern unsigned long prepare_sg(struct device *dev, struct scatterlist *sg, int nents);
+#endif /* _IOMMU_COMMON_H */
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c
index d94f901d321e..34fc3ddd5002 100644
--- a/arch/sparc64/kernel/kprobes.c
+++ b/arch/sparc64/kernel/kprobes.c
@@ -480,8 +480,117 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 	return 0;
 }
 
-/* architecture specific initialization */
-int arch_init_kprobes(void)
+/* Called with kretprobe_lock held.  The value stored in the return
+ * address register is actually 2 instructions before where the
+ * callee will return to.  Sequences usually look something like this
+ *
+ *		call	some_function	<--- return register points here
+ *		 nop			<--- call delay slot
+ *		whatever		<--- where callee returns to
+ *
+ * To keep trampoline_probe_handler logic simpler, we normalize the
+ * value kept in ri->ret_addr so we don't need to keep adjusting it
+ * back and forth.
+ */
+void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
+				      struct pt_regs *regs)
+{
+	ri->ret_addr = (kprobe_opcode_t *)(regs->u_regs[UREG_RETPC] + 8);
+
+	/* Replace the return addr with trampoline addr */
+	regs->u_regs[UREG_RETPC] =
+		((unsigned long)kretprobe_trampoline) - 8;
+}
+
+/*
+ * Called when the probe at kretprobe trampoline is hit
+ */
+int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	struct kretprobe_instance *ri = NULL;
+	struct hlist_head *head, empty_rp;
+	struct hlist_node *node, *tmp;
+	unsigned long flags, orig_ret_address = 0;
+	unsigned long trampoline_address =(unsigned long)&kretprobe_trampoline;
+
+	INIT_HLIST_HEAD(&empty_rp);
+	spin_lock_irqsave(&kretprobe_lock, flags);
+	head = kretprobe_inst_table_head(current);
+
+	/*
+	 * It is possible to have multiple instances associated with a given
+	 * task either because an multiple functions in the call path
+	 * have a return probe installed on them, and/or more then one return
+	 * return probe was registered for a target function.
+	 *
+	 * We can handle this because:
+	 *     - instances are always inserted at the head of the list
+	 *     - when multiple return probes are registered for the same
+	 *       function, the first instance's ret_addr will point to the
+	 *       real return address, and all the rest will point to
+	 *       kretprobe_trampoline
+	 */
+	hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
+		if (ri->task != current)
+			/* another task is sharing our hash bucket */
+			continue;
+
+		if (ri->rp && ri->rp->handler)
+			ri->rp->handler(ri, regs);
+
+		orig_ret_address = (unsigned long)ri->ret_addr;
+		recycle_rp_inst(ri, &empty_rp);
+
+		if (orig_ret_address != trampoline_address)
+			/*
+			 * This is the real return address. Any other
+			 * instances associated with this task are for
+			 * other calls deeper on the call stack
+			 */
+			break;
+	}
+
+	kretprobe_assert(ri, orig_ret_address, trampoline_address);
+	regs->tpc = orig_ret_address;
+	regs->tnpc = orig_ret_address + 4;
+
+	reset_current_kprobe();
+	spin_unlock_irqrestore(&kretprobe_lock, flags);
+	preempt_enable_no_resched();
+
+	hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
+		hlist_del(&ri->hlist);
+		kfree(ri);
+	}
+	/*
+	 * By returning a non-zero value, we are telling
+	 * kprobe_handler() that we don't want the post_handler
+	 * to run (and have re-enabled preemption)
+	 */
+	return 1;
+}
+
+void kretprobe_trampoline_holder(void)
+{
+	asm volatile(".global kretprobe_trampoline\n"
+		     "kretprobe_trampoline:\n"
+		     "\tnop\n"
+		     "\tnop\n");
+}
+static struct kprobe trampoline_p = {
+	.addr = (kprobe_opcode_t *) &kretprobe_trampoline,
+	.pre_handler = trampoline_probe_handler
+};
+
+int __init arch_init_kprobes(void)
 {
+	return register_kprobe(&trampoline_p);
+}
+
+int __kprobes arch_trampoline_kprobe(struct kprobe *p)
+{
+	if (p->addr == (kprobe_opcode_t *)&kretprobe_trampoline)
+		return 1;
+
 	return 0;
 }
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c
index fc5c0cc793b8..0fd9db95b896 100644
--- a/arch/sparc64/kernel/of_device.c
+++ b/arch/sparc64/kernel/of_device.c
@@ -868,29 +868,3 @@ static int __init of_debug(char *str)
 }
 
 __setup("of_debug=", of_debug);
-
-struct of_device* of_platform_device_create(struct device_node *np,
-					    const char *bus_id,
-					    struct device *parent,
-					    struct bus_type *bus)
-{
-	struct of_device *dev;
-
-	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-	if (!dev)
-		return NULL;
-
-	dev->dev.parent = parent;
-	dev->dev.bus = bus;
-	dev->dev.release = of_release_dev;
-
-	strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
-
-	if (of_device_register(dev) != 0) {
-		kfree(dev);
-		return NULL;
-	}
-
-	return dev;
-}
-EXPORT_SYMBOL(of_platform_device_create);
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c
index 61baf8dc095e..ddca6c6c0b49 100644
--- a/arch/sparc64/kernel/pci_sun4v.c
+++ b/arch/sparc64/kernel/pci_sun4v.c
@@ -1,6 +1,6 @@
 /* pci_sun4v.c: SUN4V specific PCI controller support.
  *
- * Copyright (C) 2006, 2007 David S. Miller (davem@davemloft.net)
+ * Copyright (C) 2006, 2007, 2008 David S. Miller (davem@davemloft.net)
  */
 
 #include <linux/kernel.h>
@@ -89,6 +89,17 @@ static long iommu_batch_flush(struct iommu_batch *p)
 	return 0;
 }
 
+static inline void iommu_batch_new_entry(unsigned long entry)
+{
+	struct iommu_batch *p = &__get_cpu_var(iommu_batch);
+
+	if (p->entry + p->npages == entry)
+		return;
+	if (p->entry != ~0UL)
+		iommu_batch_flush(p);
+	p->entry = entry;
+}
+
 /* Interrupts must be disabled.  */
 static inline long iommu_batch_add(u64 phys_page)
 {
@@ -113,54 +124,6 @@ static inline long iommu_batch_end(void)
 	return iommu_batch_flush(p);
 }
 
-static long arena_alloc(struct iommu_arena *arena, unsigned long npages)
-{
-	unsigned long n, i, start, end, limit;
-	int pass;
-
-	limit = arena->limit;
-	start = arena->hint;
-	pass = 0;
-
-again:
-	n = find_next_zero_bit(arena->map, limit, start);
-	end = n + npages;
-	if (unlikely(end >= limit)) {
-		if (likely(pass < 1)) {
-			limit = start;
-			start = 0;
-			pass++;
-			goto again;
-		} else {
-			/* Scanned the whole thing, give up. */
-			return -1;
-		}
-	}
-
-	for (i = n; i < end; i++) {
-		if (test_bit(i, arena->map)) {
-			start = i + 1;
-			goto again;
-		}
-	}
-
-	for (i = n; i < end; i++)
-		__set_bit(i, arena->map);
-
-	arena->hint = end;
-
-	return n;
-}
-
-static void arena_free(struct iommu_arena *arena, unsigned long base,
-		       unsigned long npages)
-{
-	unsigned long i;
-
-	for (i = base; i < (base + npages); i++)
-		__clear_bit(i, arena->map);
-}
-
 static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
 				   dma_addr_t *dma_addrp, gfp_t gfp)
 {
@@ -185,11 +148,11 @@ static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
 	iommu = dev->archdata.iommu;
 
 	spin_lock_irqsave(&iommu->lock, flags);
-	entry = arena_alloc(&iommu->arena, npages);
+	entry = iommu_range_alloc(dev, iommu, npages, NULL);
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
-	if (unlikely(entry < 0L))
-		goto arena_alloc_fail;
+	if (unlikely(entry == DMA_ERROR_CODE))
+		goto range_alloc_fail;
 
 	*dma_addrp = (iommu->page_table_map_base +
 		      (entry << IO_PAGE_SHIFT));
@@ -219,10 +182,10 @@ static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
 iommu_map_fail:
 	/* Interrupts are disabled.  */
 	spin_lock(&iommu->lock);
-	arena_free(&iommu->arena, entry, npages);
+	iommu_range_free(iommu, *dma_addrp, npages);
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
-arena_alloc_fail:
+range_alloc_fail:
 	free_pages(first_page, order);
 	return NULL;
 }
@@ -243,7 +206,7 @@ static void dma_4v_free_coherent(struct device *dev, size_t size, void *cpu,
 
 	spin_lock_irqsave(&iommu->lock, flags);
 
-	arena_free(&iommu->arena, entry, npages);
+	iommu_range_free(iommu, dvma, npages);
 
 	do {
 		unsigned long num;
@@ -281,10 +244,10 @@ static dma_addr_t dma_4v_map_single(struct device *dev, void *ptr, size_t sz,
 	npages >>= IO_PAGE_SHIFT;
 
 	spin_lock_irqsave(&iommu->lock, flags);
-	entry = arena_alloc(&iommu->arena, npages);
+	entry = iommu_range_alloc(dev, iommu, npages, NULL);
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
-	if (unlikely(entry < 0L))
+	if (unlikely(entry == DMA_ERROR_CODE))
 		goto bad;
 
 	bus_addr = (iommu->page_table_map_base +
@@ -319,7 +282,7 @@ bad:
 iommu_map_fail:
 	/* Interrupts are disabled.  */
 	spin_lock(&iommu->lock);
-	arena_free(&iommu->arena, entry, npages);
+	iommu_range_free(iommu, bus_addr, npages);
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
 	return DMA_ERROR_CODE;
@@ -350,9 +313,9 @@ static void dma_4v_unmap_single(struct device *dev, dma_addr_t bus_addr,
 
 	spin_lock_irqsave(&iommu->lock, flags);
 
-	entry = (bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT;
-	arena_free(&iommu->arena, entry, npages);
+	iommu_range_free(iommu, bus_addr, npages);
 
+	entry = (bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT;
 	do {
 		unsigned long num;
 
@@ -368,88 +331,131 @@ static void dma_4v_unmap_single(struct device *dev, dma_addr_t bus_addr,
 static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
 			 int nelems, enum dma_data_direction direction)
 {
-	unsigned long flags, npages, i, prot;
-	struct scatterlist *sg;
+	struct scatterlist *s, *outs, *segstart;
+	unsigned long flags, handle, prot;
+	dma_addr_t dma_next = 0, dma_addr;
+	unsigned int max_seg_size;
+	int outcount, incount, i;
 	struct iommu *iommu;
-	long entry, err;
-	u32 dma_base;
-
-	/* Fast path single entry scatterlists. */
-	if (nelems == 1) {
-		sglist->dma_address =
-			dma_4v_map_single(dev, sg_virt(sglist),
-					  sglist->length, direction);
-		if (unlikely(sglist->dma_address == DMA_ERROR_CODE))
-			return 0;
-		sglist->dma_length = sglist->length;
-		return 1;
-	}
+	long err;
+
+	BUG_ON(direction == DMA_NONE);
 
 	iommu = dev->archdata.iommu;
+	if (nelems == 0 || !iommu)
+		return 0;
 	
-	if (unlikely(direction == DMA_NONE))
-		goto bad;
-
-	npages = calc_npages(sglist, nelems);
+	prot = HV_PCI_MAP_ATTR_READ;
+	if (direction != DMA_TO_DEVICE)
+		prot |= HV_PCI_MAP_ATTR_WRITE;
 
-	spin_lock_irqsave(&iommu->lock, flags);
-	entry = arena_alloc(&iommu->arena, npages);
-	spin_unlock_irqrestore(&iommu->lock, flags);
+	outs = s = segstart = &sglist[0];
+	outcount = 1;
+	incount = nelems;
+	handle = 0;
 
-	if (unlikely(entry < 0L))
-		goto bad;
+	/* Init first segment length for backout at failure */
+	outs->dma_length = 0;
 
-	dma_base = iommu->page_table_map_base +
-		(entry << IO_PAGE_SHIFT);
+	spin_lock_irqsave(&iommu->lock, flags);
 
-	prot = HV_PCI_MAP_ATTR_READ;
-	if (direction != DMA_TO_DEVICE)
-		prot |= HV_PCI_MAP_ATTR_WRITE;
+	iommu_batch_start(dev, prot, ~0UL);
 
-	local_irq_save(flags);
+	max_seg_size = dma_get_max_seg_size(dev);
+	for_each_sg(sglist, s, nelems, i) {
+		unsigned long paddr, npages, entry, slen;
 
-	iommu_batch_start(dev, prot, entry);
+		slen = s->length;
+		/* Sanity check */
+		if (slen == 0) {
+			dma_next = 0;
+			continue;
+		}
+		/* Allocate iommu entries for that segment */
+		paddr = (unsigned long) SG_ENT_PHYS_ADDRESS(s);
+		npages = iommu_num_pages(paddr, slen);
+		entry = iommu_range_alloc(dev, iommu, npages, &handle);
 
-	for_each_sg(sglist, sg, nelems, i) {
-		unsigned long paddr = SG_ENT_PHYS_ADDRESS(sg);
-		unsigned long slen = sg->length;
-		unsigned long this_npages;
+		/* Handle failure */
+		if (unlikely(entry == DMA_ERROR_CODE)) {
+			if (printk_ratelimit())
+				printk(KERN_INFO "iommu_alloc failed, iommu %p paddr %lx"
+				       " npages %lx\n", iommu, paddr, npages);
+			goto iommu_map_failed;
+		}
 
-		this_npages = iommu_num_pages(paddr, slen);
+		iommu_batch_new_entry(entry);
 
-		sg->dma_address = dma_base | (paddr & ~IO_PAGE_MASK);
-		sg->dma_length = slen;
+		/* Convert entry to a dma_addr_t */
+		dma_addr = iommu->page_table_map_base +
+			(entry << IO_PAGE_SHIFT);
+		dma_addr |= (s->offset & ~IO_PAGE_MASK);
 
+		/* Insert into HW table */
 		paddr &= IO_PAGE_MASK;
-		while (this_npages--) {
+		while (npages--) {
 			err = iommu_batch_add(paddr);
-			if (unlikely(err < 0L)) {
-				local_irq_restore(flags);
+			if (unlikely(err < 0L))
 				goto iommu_map_failed;
+			paddr += IO_PAGE_SIZE;
+		}
+
+		/* If we are in an open segment, try merging */
+		if (segstart != s) {
+			/* We cannot merge if:
+			 * - allocated dma_addr isn't contiguous to previous allocation
+			 */
+			if ((dma_addr != dma_next) ||
+			    (outs->dma_length + s->length > max_seg_size)) {
+				/* Can't merge: create a new segment */
+				segstart = s;
+				outcount++;
+				outs = sg_next(outs);
+			} else {
+				outs->dma_length += s->length;
 			}
+		}
 
-			paddr += IO_PAGE_SIZE;
-			dma_base += IO_PAGE_SIZE;
+		if (segstart == s) {
+			/* This is a new segment, fill entries */
+			outs->dma_address = dma_addr;
+			outs->dma_length = slen;
 		}
+
+		/* Calculate next page pointer for contiguous check */
+		dma_next = dma_addr + slen;
 	}
 
 	err = iommu_batch_end();
 
-	local_irq_restore(flags);
-
 	if (unlikely(err < 0L))
 		goto iommu_map_failed;
 
-	return nelems;
+	spin_unlock_irqrestore(&iommu->lock, flags);
 
-bad:
-	if (printk_ratelimit())
-		WARN_ON(1);
-	return 0;
+	if (outcount < incount) {
+		outs = sg_next(outs);
+		outs->dma_address = DMA_ERROR_CODE;
+		outs->dma_length = 0;
+	}
+
+	return outcount;
 
 iommu_map_failed:
-	spin_lock_irqsave(&iommu->lock, flags);
-	arena_free(&iommu->arena, entry, npages);
+	for_each_sg(sglist, s, nelems, i) {
+		if (s->dma_length != 0) {
+			unsigned long vaddr, npages;
+
+			vaddr = s->dma_address & IO_PAGE_MASK;
+			npages = iommu_num_pages(s->dma_address, s->dma_length);
+			iommu_range_free(iommu, vaddr, npages);
+			/* XXX demap? XXX */
+			s->dma_address = DMA_ERROR_CODE;
+			s->dma_length = 0;
+		}
+		if (s == outs)
+			break;
+	}
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
 	return 0;
@@ -458,39 +464,43 @@ iommu_map_failed:
 static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist,
 			    int nelems, enum dma_data_direction direction)
 {
-	unsigned long flags, npages;
 	struct pci_pbm_info *pbm;
-	u32 devhandle, bus_addr;
+	struct scatterlist *sg;
 	struct iommu *iommu;
-	long entry;
+	unsigned long flags;
+	u32 devhandle;
 
-	if (unlikely(direction == DMA_NONE)) {
-		if (printk_ratelimit())
-			WARN_ON(1);
-	}
+	BUG_ON(direction == DMA_NONE);
 
 	iommu = dev->archdata.iommu;
 	pbm = dev->archdata.host_controller;
 	devhandle = pbm->devhandle;
 	
-	bus_addr = sglist->dma_address & IO_PAGE_MASK;
-
-	npages = calc_npages(sglist, nelems);
-
-	entry = ((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
-
 	spin_lock_irqsave(&iommu->lock, flags);
 
-	arena_free(&iommu->arena, entry, npages);
-
-	do {
-		unsigned long num;
+	sg = sglist;
+	while (nelems--) {
+		dma_addr_t dma_handle = sg->dma_address;
+		unsigned int len = sg->dma_length;
+		unsigned long npages, entry;
+
+		if (!len)
+			break;
+		npages = iommu_num_pages(dma_handle, len);
+		iommu_range_free(iommu, dma_handle, npages);
+
+		entry = ((dma_handle - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
+		while (npages) {
+			unsigned long num;
+
+			num = pci_sun4v_iommu_demap(devhandle, HV_PCI_TSBID(0, entry),
+						    npages);
+			entry += num;
+			npages -= num;
+		}
 
-		num = pci_sun4v_iommu_demap(devhandle, HV_PCI_TSBID(0, entry),
-					    npages);
-		entry += num;
-		npages -= num;
-	} while (npages != 0);
+		sg = sg_next(sg);
+	}
 
 	spin_unlock_irqrestore(&iommu->lock, flags);
 }
diff --git a/include/asm-sparc/a.out.h b/include/asm-sparc/a.out.h
index 744cfe6c0de8..2f1c3748a068 100644
--- a/include/asm-sparc/a.out.h
+++ b/include/asm-sparc/a.out.h
@@ -1,24 +1,27 @@
-/* $Id: a.out.h,v 1.13 2000/01/09 10:46:53 anton Exp $ */
 #ifndef __SPARC_A_OUT_H__
 #define __SPARC_A_OUT_H__
 
 #define SPARC_PGSIZE    0x2000        /* Thanks to the sun4 architecture... */
 #define SEGMENT_SIZE    SPARC_PGSIZE  /* whee... */
 
+#ifndef __ASSEMBLY__
+
 struct exec {
 	unsigned char a_dynamic:1;      /* A __DYNAMIC is in this image */
 	unsigned char a_toolversion:7;
 	unsigned char a_machtype;
 	unsigned short a_info;
-	unsigned long a_text;		/* length of text, in bytes */
-	unsigned long a_data;		/* length of data, in bytes */
-	unsigned long a_bss;		/* length of bss, in bytes */
-	unsigned long a_syms;		/* length of symbol table, in bytes */
-	unsigned long a_entry;		/* where program begins */
-	unsigned long a_trsize;
-	unsigned long a_drsize;
+	unsigned int a_text;		/* length of text, in bytes */
+	unsigned int a_data;		/* length of data, in bytes */
+	unsigned int a_bss;		/* length of bss, in bytes */
+	unsigned int a_syms;		/* length of symbol table, in bytes */
+	unsigned int a_entry;		/* where program begins */
+	unsigned int a_trsize;
+	unsigned int a_drsize;
 };
 
+#endif /* !__ASSEMBLY__ */
+
 /* Where in the file does the text information begin? */
 #define N_TXTOFF(x)     (N_MAGIC(x) == ZMAGIC ? 0 : sizeof (struct exec))
 
@@ -28,19 +31,21 @@ struct exec {
                          (x).a_drsize)
 
 /* Where does text segment go in memory after being loaded? */
-#define N_TXTADDR(x)    (((N_MAGIC(x) == ZMAGIC) &&        \
+#define N_TXTADDR(x)    (unsigned long)(((N_MAGIC(x) == ZMAGIC) && \
 	                 ((x).a_entry < SPARC_PGSIZE)) ?   \
                           0 : SPARC_PGSIZE)
 
 /* And same for the data segment.. */
 #define N_DATADDR(x) (N_MAGIC(x)==OMAGIC ?         \
                       (N_TXTADDR(x) + (x).a_text)  \
-                       : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
+		       : (unsigned long) (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
 
 #define N_TRSIZE(a)	((a).a_trsize)
 #define N_DRSIZE(a)	((a).a_drsize)
 #define N_SYMSIZE(a)	((a).a_syms)
 
+#ifndef __ASSEMBLY__
+
 /*
  * Sparc relocation types
  */
@@ -77,14 +82,16 @@ enum reloc_type
  */
 struct relocation_info /* used when header.a_machtype == M_SPARC */
 {
-        unsigned long   r_address;  /* relocation addr */
+        unsigned int    r_address;  /* relocation addr */
         unsigned int    r_index:24; /* segment index or symbol index */
         unsigned int    r_extern:1; /* if F, r_index==SEG#; if T, SYM idx */
         unsigned int    r_pad:2;    /* <unused> */
         enum reloc_type r_type:5;   /* type of relocation to perform */
-        long            r_addend;   /* addend for relocation value */
+        int             r_addend;   /* addend for relocation value */
 };
 
 #define N_RELOCATION_INFO_DECLARED 1
 
+#endif /* !(__ASSEMBLY__) */
+
 #endif /* __SPARC_A_OUT_H__ */
diff --git a/include/asm-sparc/bpp.h b/include/asm-sparc/bpp.h
index 3578ac113cf0..31f515e499a7 100644
--- a/include/asm-sparc/bpp.h
+++ b/include/asm-sparc/bpp.h
@@ -17,7 +17,7 @@
  * with compliant or compatible devices. It will use whatever features
  * the device supports, prefering those that are typically faster.
  *
- * When the device is opened, it is left in COMPATABILITY mode, and
+ * When the device is opened, it is left in COMPATIBILITY mode, and
  * writes work like any printer device. The driver only attempt to
  * negotiate 1284 modes when needed so that plugs can be pulled,
  * switch boxes switched, etc., without disrupting things. It will
diff --git a/include/asm-sparc/bsderrno.h b/include/asm-sparc/bsderrno.h
deleted file mode 100644
index 54a75be43abb..000000000000
--- a/include/asm-sparc/bsderrno.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/* $Id: bsderrno.h,v 1.3 1996/04/25 06:12:47 davem Exp $
- * bsderrno.h: Error numbers for NetBSD binary compatibility
- *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef _SPARC_BSDERRNO_H
-#define _SPARC_BSDERRNO_H
-
-#define BSD_EPERM         1      /* Operation not permitted */
-#define BSD_ENOENT        2      /* No such file or directory */
-#define BSD_ESRCH         3      /* No such process */
-#define BSD_EINTR         4      /* Interrupted system call */
-#define BSD_EIO           5      /* Input/output error */
-#define BSD_ENXIO         6      /* Device not configured */
-#define BSD_E2BIG         7      /* Argument list too long */
-#define BSD_ENOEXEC       8      /* Exec format error */
-#define BSD_EBADF         9      /* Bad file descriptor */
-#define BSD_ECHILD        10     /* No child processes */
-#define BSD_EDEADLK       11     /* Resource deadlock avoided */
-#define BSD_ENOMEM        12     /* Cannot allocate memory */
-#define BSD_EACCES        13     /* Permission denied */
-#define BSD_EFAULT        14     /* Bad address */
-#define BSD_ENOTBLK       15     /* Block device required */
-#define BSD_EBUSY         16     /* Device busy */
-#define BSD_EEXIST        17     /* File exists */
-#define BSD_EXDEV         18     /* Cross-device link */
-#define BSD_ENODEV        19     /* Operation not supported by device */
-#define BSD_ENOTDIR       20     /* Not a directory */
-#define BSD_EISDIR        21     /* Is a directory */
-#define BSD_EINVAL        22     /* Invalid argument */
-#define BSD_ENFILE        23     /* Too many open files in system */
-#define BSD_EMFILE        24     /* Too many open files */
-#define BSD_ENOTTY        25     /* Inappropriate ioctl for device */
-#define BSD_ETXTBSY       26     /* Text file busy */
-#define BSD_EFBIG         27     /* File too large */
-#define BSD_ENOSPC        28     /* No space left on device */
-#define BSD_ESPIPE        29     /* Illegal seek */
-#define BSD_EROFS         30     /* Read-only file system */
-#define BSD_EMLINK        31     /* Too many links */
-#define BSD_EPIPE         32     /* Broken pipe */
-#define BSD_EDOM          33     /* Numerical argument out of domain */
-#define BSD_ERANGE        34     /* Result too large */
-#define BSD_EAGAIN        35     /* Resource temporarily unavailable */
-#define BSD_EWOULDBLOCK   EAGAIN /* Operation would block */
-#define BSD_EINPROGRESS   36     /* Operation now in progress */
-#define BSD_EALREADY      37     /* Operation already in progress */
-#define BSD_ENOTSOCK      38     /* Socket operation on non-socket */
-#define BSD_EDESTADDRREQ  39     /* Destination address required */
-#define BSD_EMSGSIZE      40     /* Message too long */
-#define BSD_EPROTOTYPE    41     /* Protocol wrong type for socket */
-#define BSD_ENOPROTOOPT   42     /* Protocol not available */
-#define BSD_EPROTONOSUPPORT  43  /* Protocol not supported */
-#define BSD_ESOCKTNOSUPPORT  44  /* Socket type not supported */
-#define BSD_EOPNOTSUPP    45     /* Operation not supported */
-#define BSD_EPFNOSUPPORT  46     /* Protocol family not supported */
-#define BSD_EAFNOSUPPORT  47     /* Address family not supported by protocol family */
-#define BSD_EADDRINUSE    48     /* Address already in use */
-#define BSD_EADDRNOTAVAIL 49     /* Can't assign requested address */
-#define BSD_ENETDOWN      50     /* Network is down */
-#define BSD_ENETUNREACH   51     /* Network is unreachable */
-#define BSD_ENETRESET     52     /* Network dropped connection on reset */
-#define BSD_ECONNABORTED  53     /* Software caused connection abort */
-#define BSD_ECONNRESET    54     /* Connection reset by peer */
-#define BSD_ENOBUFS       55     /* No buffer space available */
-#define BSD_EISCONN       56     /* Socket is already connected */
-#define BSD_ENOTCONN      57     /* Socket is not connected */
-#define BSD_ESHUTDOWN     58     /* Can't send after socket shutdown */
-#define BSD_ETOOMANYREFS  59     /* Too many references: can't splice */
-#define BSD_ETIMEDOUT     60     /* Operation timed out */
-#define BSD_ECONNREFUSED  61     /* Connection refused */
-#define BSD_ELOOP         62     /* Too many levels of symbolic links */
-#define BSD_ENAMETOOLONG  63     /* File name too long */
-#define BSD_EHOSTDOWN     64     /* Host is down */
-#define BSD_EHOSTUNREACH  65     /* No route to host */
-#define BSD_ENOTEMPTY     66     /* Directory not empty */
-#define BSD_EPROCLIM      67     /* Too many processes */
-#define BSD_EUSERS        68     /* Too many users */
-#define BSD_EDQUOT        69     /* Disc quota exceeded */
-#define BSD_ESTALE        70     /* Stale NFS file handle */
-#define BSD_EREMOTE       71     /* Too many levels of remote in path */
-#define BSD_EBADRPC       72     /* RPC struct is bad */
-#define BSD_ERPCMISMATCH  73     /* RPC version wrong */
-#define BSD_EPROGUNAVAIL  74     /* RPC prog. not avail */
-#define BSD_EPROGMISMATCH 75     /* Program version wrong */
-#define BSD_EPROCUNAVAIL  76     /* Bad procedure for program */
-#define BSD_ENOLCK        77     /* No locks available */
-#define BSD_ENOSYS        78     /* Function not implemented */
-#define BSD_EFTYPE        79     /* Inappropriate file type or format */
-#define BSD_EAUTH         80     /* Authentication error */
-#define BSD_ENEEDAUTH     81     /* Need authenticator */
-#define BSD_ELAST         81     /* Must be equal largest errno */
-
-#endif /* !(_SPARC_BSDERRNO_H) */
diff --git a/include/asm-sparc/bug.h b/include/asm-sparc/bug.h
index 04151208189f..8a59e5a8c217 100644
--- a/include/asm-sparc/bug.h
+++ b/include/asm-sparc/bug.h
@@ -2,28 +2,16 @@
 #define _SPARC_BUG_H
 
 #ifdef CONFIG_BUG
-/* Only use the inline asm until a gcc release that can handle __builtin_trap
- * -rob 2003-06-25
- *
- * gcc-3.3.1 and later will be OK -DaveM
- */
-#if (__GNUC__ > 3) || \
-    (__GNUC__ == 3 && __GNUC_MINOR__ > 3) || \
-    (__GNUC__ == 3 && __GNUC_MINOR__ == 3 && __GNUC_PATCHLEVEL__ >= 4)
-#define __bug_trap()		__builtin_trap()
-#else
-#define __bug_trap()					\
-	__asm__ __volatile__ ("t 0x5\n\t" : : )
-#endif
+#include <linux/compiler.h>
 
 #ifdef CONFIG_DEBUG_BUGVERBOSE
 extern void do_BUG(const char *file, int line);
 #define BUG() do {					\
 	do_BUG(__FILE__, __LINE__);			\
-	__bug_trap();				\
+	__builtin_trap();				\
 } while (0)
 #else
-#define BUG()		__bug_trap()
+#define BUG()		__builtin_trap()
 #endif
 
 #define HAVE_ARCH_BUG
diff --git a/include/asm-sparc/bugs.h b/include/asm-sparc/bugs.h
index a0f939beeea1..2dfc07bc8e54 100644
--- a/include/asm-sparc/bugs.h
+++ b/include/asm-sparc/bugs.h
@@ -1,16 +1,24 @@
-/*  $Id: bugs.h,v 1.1 1996/12/26 13:25:20 davem Exp $
- *  include/asm-sparc/bugs.h:  Sparc probes for various bugs.
+/* include/asm-sparc/bugs.h:  Sparc probes for various bugs.
  *
- *  Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996, 2007 David S. Miller (davem@davemloft.net)
  */
 
+#ifdef CONFIG_SPARC32
 #include <asm/cpudata.h>
+#endif
+
+#ifdef CONFIG_SPARC64
+#include <asm/sstate.h>
+#endif
 
 extern unsigned long loops_per_jiffy;
 
-static void check_bugs(void)
+static void __init check_bugs(void)
 {
-#ifndef CONFIG_SMP
+#if defined(CONFIG_SPARC32) && !defined(CONFIG_SMP)
 	cpu_data(0).udelay_val = loops_per_jiffy;
 #endif
+#ifdef CONFIG_SPARC64
+	sstate_running();
+#endif
 }
diff --git a/include/asm-sparc/byteorder.h b/include/asm-sparc/byteorder.h
index a2949aea48ef..bcd83aa351c5 100644
--- a/include/asm-sparc/byteorder.h
+++ b/include/asm-sparc/byteorder.h
@@ -1,12 +1,55 @@
-/* $Id: byteorder.h,v 1.15 1997/12/16 19:20:44 davem Exp $ */
 #ifndef _SPARC_BYTEORDER_H
 #define _SPARC_BYTEORDER_H
 
 #include <asm/types.h>
+#include <asm/asi.h>
+
+#ifdef __GNUC__
+
+#ifdef CONFIG_SPARC32
+#define __SWAB_64_THRU_32__
+#endif
+
+#ifdef CONFIG_SPARC64
+
+static inline __u16 ___arch__swab16p(const __u16 *addr)
+{
+	__u16 ret;
+
+	__asm__ __volatile__ ("lduha [%1] %2, %0"
+			      : "=r" (ret)
+			      : "r" (addr), "i" (ASI_PL));
+	return ret;
+}
+
+static inline __u32 ___arch__swab32p(const __u32 *addr)
+{
+	__u32 ret;
+
+	__asm__ __volatile__ ("lduwa [%1] %2, %0"
+			      : "=r" (ret)
+			      : "r" (addr), "i" (ASI_PL));
+	return ret;
+}
+
+static inline __u64 ___arch__swab64p(const __u64 *addr)
+{
+	__u64 ret;
+
+	__asm__ __volatile__ ("ldxa [%1] %2, %0"
+			      : "=r" (ret)
+			      : "r" (addr), "i" (ASI_PL));
+	return ret;
+}
+
+#define __arch__swab16p(x) ___arch__swab16p(x)
+#define __arch__swab32p(x) ___arch__swab32p(x)
+#define __arch__swab64p(x) ___arch__swab64p(x)
+
+#endif /* CONFIG_SPARC64 */
+
+#define __BYTEORDER_HAS_U64__
 
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
-#  define __BYTEORDER_HAS_U64__
-#  define __SWAB_64_THRU_32__
 #endif
 
 #include <linux/byteorder/big_endian.h>
diff --git a/include/asm-sparc/cache.h b/include/asm-sparc/cache.h
index cb971e88aea4..41f85ae4bd4a 100644
--- a/include/asm-sparc/cache.h
+++ b/include/asm-sparc/cache.h
@@ -1,20 +1,28 @@
-/* $Id: cache.h,v 1.9 1999/08/14 03:51:58 anton Exp $
- * cache.h:  Cache specific code for the Sparc.  These include flushing
+/* cache.h:  Cache specific code for the Sparc.  These include flushing
  *           and direct tag/data line access.
  *
- * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net)
  */
 
 #ifndef _SPARC_CACHE_H
 #define _SPARC_CACHE_H
 
-#include <asm/asi.h>
-
 #define L1_CACHE_SHIFT 5
 #define L1_CACHE_BYTES 32
 #define L1_CACHE_ALIGN(x) ((((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1)))
 
-#define SMP_CACHE_BYTES 32
+#ifdef CONFIG_SPARC32
+#define SMP_CACHE_BYTES_SHIFT 5
+#else
+#define SMP_CACHE_BYTES_SHIFT 6
+#endif
+
+#define SMP_CACHE_BYTES (1 << SMP_CACHE_BYTES_SHIFT)
+
+#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+
+#ifdef CONFIG_SPARC32
+#include <asm/asi.h>
 
 /* Direct access to the instruction cache is provided through and
  * alternate address space.  The IDC bit must be off in the ICCR on
@@ -125,5 +133,6 @@ static inline void flush_ei_user(unsigned int addr)
 			     "r" (addr), "i" (ASI_M_FLUSH_USER) :
 			     "memory");
 }
+#endif /* CONFIG_SPARC32 */
 
 #endif /* !(_SPARC_CACHE_H) */
diff --git a/include/asm-sparc/current.h b/include/asm-sparc/current.h
index 8fe7c82a5e21..8a1d9d6643b0 100644
--- a/include/asm-sparc/current.h
+++ b/include/asm-sparc/current.h
@@ -1,31 +1,34 @@
-/*
- *  include/asm-sparc/current.h
+/* include/asm-sparc/current.h
  *
  * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
  * Copyright (C) 2002 Pete Zaitcev (zaitcev@yahoo.com)
+ * Copyright (C) 2007 David S. Miller (davem@davemloft.net)
  *
  *  Derived from "include/asm-s390/current.h" by
  *  Martin Schwidefsky (schwidefsky@de.ibm.com)
  *  Derived from "include/asm-i386/current.h"
- */
-#ifndef _ASM_CURRENT_H
-#define _ASM_CURRENT_H
-
-/*
- * At the sparc64 DaveM keeps current_thread_info in %g4.
- * We might want to consider doing the same to shave a few cycles.
- */
+*/
+#ifndef _SPARC_CURRENT_H
+#define _SPARC_CURRENT_H
 
 #include <linux/thread_info.h>
 
-struct task_struct;
+#ifdef CONFIG_SPARC64
+register struct task_struct *current asm("g4");
+#endif
 
-/* Two stage process (inline + #define) for type-checking. */
-/* We also obfuscate get_current() to check if anyone used that by mistake. */
+#ifdef CONFIG_SPARC32
+/* We might want to consider using %g4 like sparc64 to shave a few cycles.
+ *
+ * Two stage process (inline + #define) for type-checking.
+ * We also obfuscate get_current() to check if anyone used that by mistake.
+ */
+struct task_struct;
 static inline struct task_struct *__get_current(void)
 {
 	return current_thread_info()->task;
 }
 #define current __get_current()
+#endif
 
-#endif /* !(_ASM_CURRENT_H) */
+#endif /* !(_SPARC_CURRENT_H) */
diff --git a/include/asm-sparc/device.h b/include/asm-sparc/device.h
index c0a7786d65f7..680e51d87374 100644
--- a/include/asm-sparc/device.h
+++ b/include/asm-sparc/device.h
@@ -19,5 +19,3 @@ struct dev_archdata {
 };
 
 #endif /* _ASM_SPARC_DEVICE_H */
-
-
diff --git a/include/asm-sparc/errno.h b/include/asm-sparc/errno.h
index ed41c8bac1fa..a9ef172977de 100644
--- a/include/asm-sparc/errno.h
+++ b/include/asm-sparc/errno.h
@@ -1,4 +1,3 @@
-/* $Id: errno.h,v 1.6 1997/04/15 09:03:38 davem Exp $ */
 #ifndef _SPARC_ERRNO_H
 #define _SPARC_ERRNO_H
 
diff --git a/include/asm-sparc/fb.h b/include/asm-sparc/fb.h
index c73ca081e1f5..b83e44729655 100644
--- a/include/asm-sparc/fb.h
+++ b/include/asm-sparc/fb.h
@@ -1,9 +1,17 @@
-#ifndef _ASM_FB_H_
-#define _ASM_FB_H_
+#ifndef _SPARC_FB_H_
+#define _SPARC_FB_H_
 #include <linux/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
 #include <asm/prom.h>
 
-#define fb_pgprotect(...) do {} while (0)
+static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
+				unsigned long off)
+{
+#ifdef CONFIG_SPARC64
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+#endif
+}
 
 static inline int fb_is_primary_device(struct fb_info *info)
 {
@@ -18,4 +26,4 @@ static inline int fb_is_primary_device(struct fb_info *info)
 	return 0;
 }
 
-#endif /* _ASM_FB_H_ */
+#endif /* _SPARC_FB_H_ */
diff --git a/include/asm-sparc/of_platform.h b/include/asm-sparc/of_platform.h
index d638737ff13c..38334351c36b 100644
--- a/include/asm-sparc/of_platform.h
+++ b/include/asm-sparc/of_platform.h
@@ -21,9 +21,4 @@ extern struct bus_type sbus_bus_type;
 
 #define of_bus_type	of_platform_bus_type	/* for compatibility */
 
-extern struct of_device *of_platform_device_create(struct device_node *np,
-						   const char *bus_id,
-						   struct device *parent,
-						   struct bus_type *bus);
-
 #endif	/* _ASM_SPARC_OF_PLATFORM_H */
diff --git a/include/asm-sparc/prom.h b/include/asm-sparc/prom.h
index 71f2a1998324..df5dc4422483 100644
--- a/include/asm-sparc/prom.h
+++ b/include/asm-sparc/prom.h
@@ -9,7 +9,7 @@
  * Copyright (C) 1996-2005 Paul Mackerras.
  *
  * Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp.
- * Updates for SPARC32 by David S. Miller
+ * Updates for SPARC by David S. Miller
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -39,6 +39,7 @@ struct property {
 	unsigned int unique_id;
 };
 
+struct of_irq_controller;
 struct device_node {
 	const char	*name;
 	const char	*type;
@@ -58,11 +59,19 @@ struct device_node {
 	unsigned long _flags;
 	void	*data;
 	unsigned int unique_id;
+
+	struct of_irq_controller *irq_trans;
+};
+
+struct of_irq_controller {
+	unsigned int	(*irq_build)(struct device_node *, unsigned int, void *);
+	void		*data;
 };
 
 #define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
 #define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
 
+extern struct device_node *of_find_node_by_cpuid(int cpuid);
 extern int of_set_property(struct device_node *node, const char *name, void *val, int len);
 extern int of_getintprop_default(struct device_node *np,
 				 const char *name,
diff --git a/include/asm-sparc64/a.out.h b/include/asm-sparc64/a.out.h
index 53c95bdfc66e..44208c2a188e 100644
--- a/include/asm-sparc64/a.out.h
+++ b/include/asm-sparc64/a.out.h
@@ -1,98 +1 @@
-/* $Id: a.out.h,v 1.8 2002/02/09 19:49:31 davem Exp $ */
-#ifndef __SPARC64_A_OUT_H__
-#define __SPARC64_A_OUT_H__
-
-#define SPARC_PGSIZE    0x2000        /* Thanks to the sun4 architecture... */
-#define SEGMENT_SIZE    SPARC_PGSIZE  /* whee... */
-
-#ifndef __ASSEMBLY__
-
-struct exec {
-	unsigned char a_dynamic:1;      /* A __DYNAMIC is in this image */
-	unsigned char a_toolversion:7;
-	unsigned char a_machtype;
-	unsigned short a_info;
-	unsigned int a_text;		/* length of text, in bytes */
-	unsigned int a_data;		/* length of data, in bytes */
-	unsigned int a_bss;		/* length of bss, in bytes */
-	unsigned int a_syms;		/* length of symbol table, in bytes */
-	unsigned int a_entry;		/* where program begins */
-	unsigned int a_trsize;
-	unsigned int a_drsize;
-};
-
-#endif /* !__ASSEMBLY__ */
-
-/* Where in the file does the text information begin? */
-#define N_TXTOFF(x)     (N_MAGIC(x) == ZMAGIC ? 0 : sizeof (struct exec))
-
-/* Where do the Symbols start? */
-#define N_SYMOFF(x)     (N_TXTOFF(x) + (x).a_text +   \
-                         (x).a_data + (x).a_trsize +  \
-                         (x).a_drsize)
-
-/* Where does text segment go in memory after being loaded? */
-#define N_TXTADDR(x)    (unsigned long)(((N_MAGIC(x) == ZMAGIC) &&      \
-	                 ((x).a_entry < SPARC_PGSIZE)) ?   		\
-                          0 : SPARC_PGSIZE)
-
-/* And same for the data segment.. */
-#define N_DATADDR(x) (N_MAGIC(x)==OMAGIC ?         \
-                      (N_TXTADDR(x) + (x).a_text)  \
-                       : (unsigned long)(_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
-
-#define N_TRSIZE(a)	((a).a_trsize)
-#define N_DRSIZE(a)	((a).a_drsize)
-#define N_SYMSIZE(a)	((a).a_syms)
-
-#ifndef __ASSEMBLY__
-
-/*
- * Sparc relocation types
- */
-enum reloc_type
-{
-	RELOC_8,
-	RELOC_16,
-	RELOC_32,	/* simplest relocs */
-	RELOC_DISP8,
-	RELOC_DISP16,
-	RELOC_DISP32,	/* Disp's (pc-rel) */
-	RELOC_WDISP30,
-	RELOC_WDISP22,  /* SR word disp's */
-	RELOC_HI22,
-	RELOC_22,	/* SR 22-bit relocs */
-	RELOC_13,
-	RELOC_LO10,	/* SR 13&10-bit relocs */
-	RELOC_SFA_BASE,
-	RELOC_SFA_OFF13, /* SR S.F.A. relocs */
-	RELOC_BASE10,
-	RELOC_BASE13,
-	RELOC_BASE22,	/* base_relative pic */
-	RELOC_PC10,
-	RELOC_PC22,	/* special pc-rel pic */
-	RELOC_JMP_TBL,	/* jmp_tbl_rel in pic */
-	RELOC_SEGOFF16,	/* ShLib offset-in-seg */
-	RELOC_GLOB_DAT,
-	RELOC_JMP_SLOT,
-	RELOC_RELATIVE 	/* rtld relocs */
-};
-
-/*
- * Format of a relocation datum.
- */
-struct relocation_info /* used when header.a_machtype == M_SPARC */
-{
-        unsigned int    r_address;  /* relocation addr */
-        unsigned int    r_index:24; /* segment index or symbol index */
-        unsigned int    r_extern:1; /* if F, r_index==SEG#; if T, SYM idx */
-        unsigned int    r_pad:2;    /* <unused> */
-        enum reloc_type r_type:5;   /* type of relocation to perform */
-        int             r_addend;   /* addend for relocation value */
-};
-
-#define N_RELOCATION_INFO_DECLARED 1
-
-#endif /* !(__ASSEMBLY__) */
-
-#endif /* !(__SPARC64_A_OUT_H__) */
+#include <asm-sparc/a.out.h>
diff --git a/include/asm-sparc64/auxvec.h b/include/asm-sparc64/auxvec.h
index 436a29129828..1f45c67d7316 100644
--- a/include/asm-sparc64/auxvec.h
+++ b/include/asm-sparc64/auxvec.h
@@ -1,4 +1 @@
-#ifndef __ASM_SPARC64_AUXVEC_H
-#define __ASM_SPARC64_AUXVEC_H
-
-#endif /* !(__ASM_SPARC64_AUXVEC_H) */
+#include <asm-sparc/auxvec.h>
diff --git a/include/asm-sparc64/bpp.h b/include/asm-sparc64/bpp.h
index abe163a50382..514eee20272e 100644
--- a/include/asm-sparc64/bpp.h
+++ b/include/asm-sparc64/bpp.h
@@ -1,73 +1 @@
-#ifndef _SPARC64_BPP_H
-#define _SPARC64_BPP_H
-
-/*
- * Copyright (c) 1995 Picture Elements
- *	Stephen Williams
- *	Gus Baldauf
- *
- * Linux/SPARC port by Peter Zaitcev.
- * Integration into SPARC tree by Tom Dyas.
- */
-
-#include  <linux/ioctl.h>
-
-/*
- * This is a driver that supports IEEE Std 1284-1994 communications
- * with compliant or compatible devices. It will use whatever features
- * the device supports, prefering those that are typically faster.
- *
- * When the device is opened, it is left in COMPATIBILITY mode, and
- * writes work like any printer device. The driver only attempt to
- * negotiate 1284 modes when needed so that plugs can be pulled,
- * switch boxes switched, etc., without disrupting things. It will
- * also leave the device in compatibility mode when closed.
- */
-
-
-
-/*
- * This driver also supplies ioctls to manually manipulate the
- * pins. This is great for testing devices, or writing code to deal
- * with bizzarro-mode of the ACME Special TurboThingy Plus.
- *
- * NOTE: These ioctl currently do not interact well with
- * read/write. Caveat emptor.
- *
- * PUT_PINS allows us to assign the sense of all the pins, including
- * the data pins if being driven by the host. The GET_PINS returns the
- * pins that the peripheral drives, including data if appropriate.
- */
-
-# define BPP_PUT_PINS _IOW('B', 1, int)
-# define BPP_GET_PINS _IOR('B', 2, char) /* that's bogus - should've been _IO */
-# define BPP_PUT_DATA _IOW('B', 3, int)
-# define BPP_GET_DATA _IOR('B', 4, char) /* ditto */
-
-/*
- * Set the data bus to input mode. Disengage the data bin driver and
- * be prepared to read values from the peripheral. If the arg is 0,
- * then revert the bus to output mode.
- */
-# define BPP_SET_INPUT _IOW('B', 5, int)
-
-/*
- * These bits apply to the PUT operation...
- */
-# define BPP_PP_nStrobe   0x0001
-# define BPP_PP_nAutoFd   0x0002
-# define BPP_PP_nInit     0x0004
-# define BPP_PP_nSelectIn 0x0008
-
-/*
- * These apply to the GET operation, which also reads the current value
- * of the previously put values. A bit mask of these will be returned
- * as a bit mask in the return code of the ioctl().
- */
-# define BPP_GP_nAck   0x0100
-# define BPP_GP_Busy   0x0200
-# define BPP_GP_PError 0x0400
-# define BPP_GP_Select 0x0800
-# define BPP_GP_nFault 0x1000
-
-#endif
+#include <asm-sparc/bpp.h>
diff --git a/include/asm-sparc64/bsderrno.h b/include/asm-sparc64/bsderrno.h
deleted file mode 100644
index 52fe880d2af8..000000000000
--- a/include/asm-sparc64/bsderrno.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/* $Id: bsderrno.h,v 1.1 1996/12/26 13:25:21 davem Exp $
- * bsderrno.h: Error numbers for NetBSD binary compatibility
- *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
- */
-
-#ifndef _SPARC64_BSDERRNO_H
-#define _SPARC64_BSDERRNO_H
-
-#define BSD_EPERM         1      /* Operation not permitted */
-#define BSD_ENOENT        2      /* No such file or directory */
-#define BSD_ESRCH         3      /* No such process */
-#define BSD_EINTR         4      /* Interrupted system call */
-#define BSD_EIO           5      /* Input/output error */
-#define BSD_ENXIO         6      /* Device not configured */
-#define BSD_E2BIG         7      /* Argument list too long */
-#define BSD_ENOEXEC       8      /* Exec format error */
-#define BSD_EBADF         9      /* Bad file descriptor */
-#define BSD_ECHILD        10     /* No child processes */
-#define BSD_EDEADLK       11     /* Resource deadlock avoided */
-#define BSD_ENOMEM        12     /* Cannot allocate memory */
-#define BSD_EACCES        13     /* Permission denied */
-#define BSD_EFAULT        14     /* Bad address */
-#define BSD_ENOTBLK       15     /* Block device required */
-#define BSD_EBUSY         16     /* Device busy */
-#define BSD_EEXIST        17     /* File exists */
-#define BSD_EXDEV         18     /* Cross-device link */
-#define BSD_ENODEV        19     /* Operation not supported by device */
-#define BSD_ENOTDIR       20     /* Not a directory */
-#define BSD_EISDIR        21     /* Is a directory */
-#define BSD_EINVAL        22     /* Invalid argument */
-#define BSD_ENFILE        23     /* Too many open files in system */
-#define BSD_EMFILE        24     /* Too many open files */
-#define BSD_ENOTTY        25     /* Inappropriate ioctl for device */
-#define BSD_ETXTBSY       26     /* Text file busy */
-#define BSD_EFBIG         27     /* File too large */
-#define BSD_ENOSPC        28     /* No space left on device */
-#define BSD_ESPIPE        29     /* Illegal seek */
-#define BSD_EROFS         30     /* Read-only file system */
-#define BSD_EMLINK        31     /* Too many links */
-#define BSD_EPIPE         32     /* Broken pipe */
-#define BSD_EDOM          33     /* Numerical argument out of domain */
-#define BSD_ERANGE        34     /* Result too large */
-#define BSD_EAGAIN        35     /* Resource temporarily unavailable */
-#define BSD_EWOULDBLOCK   EAGAIN /* Operation would block */
-#define BSD_EINPROGRESS   36     /* Operation now in progress */
-#define BSD_EALREADY      37     /* Operation already in progress */
-#define BSD_ENOTSOCK      38     /* Socket operation on non-socket */
-#define BSD_EDESTADDRREQ  39     /* Destination address required */
-#define BSD_EMSGSIZE      40     /* Message too long */
-#define BSD_EPROTOTYPE    41     /* Protocol wrong type for socket */
-#define BSD_ENOPROTOOPT   42     /* Protocol not available */
-#define BSD_EPROTONOSUPPORT  43  /* Protocol not supported */
-#define BSD_ESOCKTNOSUPPORT  44  /* Socket type not supported */
-#define BSD_EOPNOTSUPP    45     /* Operation not supported */
-#define BSD_EPFNOSUPPORT  46     /* Protocol family not supported */
-#define BSD_EAFNOSUPPORT  47     /* Address family not supported by protocol family */
-#define BSD_EADDRINUSE    48     /* Address already in use */
-#define BSD_EADDRNOTAVAIL 49     /* Can't assign requested address */
-#define BSD_ENETDOWN      50     /* Network is down */
-#define BSD_ENETUNREACH   51     /* Network is unreachable */
-#define BSD_ENETRESET     52     /* Network dropped connection on reset */
-#define BSD_ECONNABORTED  53     /* Software caused connection abort */
-#define BSD_ECONNRESET    54     /* Connection reset by peer */
-#define BSD_ENOBUFS       55     /* No buffer space available */
-#define BSD_EISCONN       56     /* Socket is already connected */
-#define BSD_ENOTCONN      57     /* Socket is not connected */
-#define BSD_ESHUTDOWN     58     /* Can't send after socket shutdown */
-#define BSD_ETOOMANYREFS  59     /* Too many references: can't splice */
-#define BSD_ETIMEDOUT     60     /* Operation timed out */
-#define BSD_ECONNREFUSED  61     /* Connection refused */
-#define BSD_ELOOP         62     /* Too many levels of symbolic links */
-#define BSD_ENAMETOOLONG  63     /* File name too long */
-#define BSD_EHOSTDOWN     64     /* Host is down */
-#define BSD_EHOSTUNREACH  65     /* No route to host */
-#define BSD_ENOTEMPTY     66     /* Directory not empty */
-#define BSD_EPROCLIM      67     /* Too many processes */
-#define BSD_EUSERS        68     /* Too many users */
-#define BSD_EDQUOT        69     /* Disc quota exceeded */
-#define BSD_ESTALE        70     /* Stale NFS file handle */
-#define BSD_EREMOTE       71     /* Too many levels of remote in path */
-#define BSD_EBADRPC       72     /* RPC struct is bad */
-#define BSD_ERPCMISMATCH  73     /* RPC version wrong */
-#define BSD_EPROGUNAVAIL  74     /* RPC prog. not avail */
-#define BSD_EPROGMISMATCH 75     /* Program version wrong */
-#define BSD_EPROCUNAVAIL  76     /* Bad procedure for program */
-#define BSD_ENOLCK        77     /* No locks available */
-#define BSD_ENOSYS        78     /* Function not implemented */
-#define BSD_EFTYPE        79     /* Inappropriate file type or format */
-#define BSD_EAUTH         80     /* Authentication error */
-#define BSD_ENEEDAUTH     81     /* Need authenticator */
-#define BSD_ELAST         81     /* Must be equal largest errno */
-
-#endif /* !(_SPARC64_BSDERRNO_H) */
diff --git a/include/asm-sparc64/bug.h b/include/asm-sparc64/bug.h
index 516bb27f3fc4..3433737c7a67 100644
--- a/include/asm-sparc64/bug.h
+++ b/include/asm-sparc64/bug.h
@@ -1,22 +1 @@
-#ifndef _SPARC64_BUG_H
-#define _SPARC64_BUG_H
-
-#ifdef CONFIG_BUG
-#include <linux/compiler.h>
-
-#ifdef CONFIG_DEBUG_BUGVERBOSE
-extern void do_BUG(const char *file, int line);
-#define BUG() do {					\
-	do_BUG(__FILE__, __LINE__);			\
-	__builtin_trap();				\
-} while (0)
-#else
-#define BUG()		__builtin_trap()
-#endif
-
-#define HAVE_ARCH_BUG
-#endif
-
-#include <asm-generic/bug.h>
-
-#endif
+#include <asm-sparc/bug.h>
diff --git a/include/asm-sparc64/bugs.h b/include/asm-sparc64/bugs.h
index 11ade6841971..04ae9e2818cf 100644
--- a/include/asm-sparc64/bugs.h
+++ b/include/asm-sparc64/bugs.h
@@ -1,10 +1 @@
-/* bugs.h: Sparc64 probes for various bugs.
- *
- * Copyright (C) 1996, 2007 David S. Miller (davem@davemloft.net)
- */
-#include <asm/sstate.h>
-
-static void __init check_bugs(void)
-{
-	sstate_running();
-}
+#include <asm-sparc/bugs.h>
diff --git a/include/asm-sparc64/byteorder.h b/include/asm-sparc64/byteorder.h
index 3943022906fd..f672855bee17 100644
--- a/include/asm-sparc64/byteorder.h
+++ b/include/asm-sparc64/byteorder.h
@@ -1,49 +1 @@
-#ifndef _SPARC64_BYTEORDER_H
-#define _SPARC64_BYTEORDER_H
-
-#include <asm/types.h>
-#include <asm/asi.h>
-
-#ifdef __GNUC__
-
-static inline __u16 ___arch__swab16p(const __u16 *addr)
-{
-	__u16 ret;
-
-	__asm__ __volatile__ ("lduha [%1] %2, %0"
-			      : "=r" (ret)
-			      : "r" (addr), "i" (ASI_PL));
-	return ret;
-}
-
-static inline __u32 ___arch__swab32p(const __u32 *addr)
-{
-	__u32 ret;
-
-	__asm__ __volatile__ ("lduwa [%1] %2, %0"
-			      : "=r" (ret)
-			      : "r" (addr), "i" (ASI_PL));
-	return ret;
-}
-
-static inline __u64 ___arch__swab64p(const __u64 *addr)
-{
-	__u64 ret;
-
-	__asm__ __volatile__ ("ldxa [%1] %2, %0"
-			      : "=r" (ret)
-			      : "r" (addr), "i" (ASI_PL));
-	return ret;
-}
-
-#define __arch__swab16p(x) ___arch__swab16p(x)
-#define __arch__swab32p(x) ___arch__swab32p(x)
-#define __arch__swab64p(x) ___arch__swab64p(x)
-
-#define __BYTEORDER_HAS_U64__
-
-#endif /* __GNUC__ */
-
-#include <linux/byteorder/big_endian.h>
-
-#endif /* _SPARC64_BYTEORDER_H */
+#include <asm-sparc/byteorder.h>
diff --git a/include/asm-sparc64/cache.h b/include/asm-sparc64/cache.h
index e9df17acedde..fa9de5cadbf1 100644
--- a/include/asm-sparc64/cache.h
+++ b/include/asm-sparc64/cache.h
@@ -1,18 +1 @@
-/*
- * include/asm-sparc64/cache.h
- */
-#ifndef __ARCH_SPARC64_CACHE_H
-#define __ARCH_SPARC64_CACHE_H
-
-/* bytes per L1 cache line */
-#define        L1_CACHE_SHIFT	5
-#define        L1_CACHE_BYTES	32 /* Two 16-byte sub-blocks per line. */
-
-#define        L1_CACHE_ALIGN(x)       (((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1))
-
-#define        SMP_CACHE_BYTES_SHIFT	6
-#define        SMP_CACHE_BYTES		(1 << SMP_CACHE_BYTES_SHIFT) /* L2 cache line size. */
-
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
-
-#endif
+#include <asm-sparc/cache.h>
diff --git a/include/asm-sparc64/cputime.h b/include/asm-sparc64/cputime.h
index dec2fc7a36f8..435f37a92f7c 100644
--- a/include/asm-sparc64/cputime.h
+++ b/include/asm-sparc64/cputime.h
@@ -1,6 +1 @@
-#ifndef __SPARC64_CPUTIME_H
-#define __SPARC64_CPUTIME_H
-
-#include <asm-generic/cputime.h>
-
-#endif /* __SPARC64_CPUTIME_H */
+#include <asm-sparc/cputime.h>
diff --git a/include/asm-sparc64/current.h b/include/asm-sparc64/current.h
index 6c21e4ee2475..a7904a7f53a8 100644
--- a/include/asm-sparc64/current.h
+++ b/include/asm-sparc64/current.h
@@ -1,8 +1 @@
-#ifndef _SPARC64_CURRENT_H
-#define _SPARC64_CURRENT_H
-
-#include <linux/thread_info.h>
-
-register struct task_struct *current asm("g4");
-
-#endif /* !(_SPARC64_CURRENT_H) */
+#include <asm-sparc/current.h>
diff --git a/include/asm-sparc64/device.h b/include/asm-sparc64/device.h
index 5111e8717be3..4145c47097e2 100644
--- a/include/asm-sparc64/device.h
+++ b/include/asm-sparc64/device.h
@@ -1,21 +1 @@
-/*
- * Arch specific extensions to struct device
- *
- * This file is released under the GPLv2
- */
-#ifndef _ASM_SPARC64_DEVICE_H
-#define _ASM_SPARC64_DEVICE_H
-
-struct device_node;
-struct of_device;
-
-struct dev_archdata {
-	void			*iommu;
-	void			*stc;
-	void			*host_controller;
-
-	struct device_node	*prom_node;
-	struct of_device	*op;
-};
-
-#endif /* _ASM_SPARC64_DEVICE_H */
+#include <asm-sparc/device.h>
diff --git a/include/asm-sparc64/div64.h b/include/asm-sparc64/div64.h
index 6cd978cefb28..928c94f99ecf 100644
--- a/include/asm-sparc64/div64.h
+++ b/include/asm-sparc64/div64.h
@@ -1 +1 @@
-#include <asm-generic/div64.h>
+#include <asm-sparc/div64.h>
diff --git a/include/asm-sparc64/emergency-restart.h b/include/asm-sparc64/emergency-restart.h
index 108d8c48e42e..2cac7b644da8 100644
--- a/include/asm-sparc64/emergency-restart.h
+++ b/include/asm-sparc64/emergency-restart.h
@@ -1,6 +1 @@
-#ifndef _ASM_EMERGENCY_RESTART_H
-#define _ASM_EMERGENCY_RESTART_H
-
-#include <asm-generic/emergency-restart.h>
-
-#endif /* _ASM_EMERGENCY_RESTART_H */
+#include <asm-sparc/emergency-restart.h>
diff --git a/include/asm-sparc64/errno.h b/include/asm-sparc64/errno.h
index ea3509ee1b0b..9701fe01cc53 100644
--- a/include/asm-sparc64/errno.h
+++ b/include/asm-sparc64/errno.h
@@ -1,114 +1 @@
-/* $Id: errno.h,v 1.2 1997/04/15 12:46:11 jj Exp $ */
-#ifndef _SPARC64_ERRNO_H
-#define _SPARC64_ERRNO_H
-
-/* These match the SunOS error numbering scheme. */
-
-#include <asm-generic/errno-base.h>
-
-#define	EWOULDBLOCK	EAGAIN	/* Operation would block */
-#define	EINPROGRESS	36	/* Operation now in progress */
-#define	EALREADY	37	/* Operation already in progress */
-#define	ENOTSOCK	38	/* Socket operation on non-socket */
-#define	EDESTADDRREQ	39	/* Destination address required */
-#define	EMSGSIZE	40	/* Message too long */
-#define	EPROTOTYPE	41	/* Protocol wrong type for socket */
-#define	ENOPROTOOPT	42	/* Protocol not available */
-#define	EPROTONOSUPPORT	43	/* Protocol not supported */
-#define	ESOCKTNOSUPPORT	44	/* Socket type not supported */
-#define	EOPNOTSUPP	45	/* Op not supported on transport endpoint */
-#define	EPFNOSUPPORT	46	/* Protocol family not supported */
-#define	EAFNOSUPPORT	47	/* Address family not supported by protocol */
-#define	EADDRINUSE	48	/* Address already in use */
-#define	EADDRNOTAVAIL	49	/* Cannot assign requested address */
-#define	ENETDOWN	50	/* Network is down */
-#define	ENETUNREACH	51	/* Network is unreachable */
-#define	ENETRESET	52	/* Net dropped connection because of reset */
-#define	ECONNABORTED	53	/* Software caused connection abort */
-#define	ECONNRESET	54	/* Connection reset by peer */
-#define	ENOBUFS		55	/* No buffer space available */
-#define	EISCONN		56	/* Transport endpoint is already connected */
-#define	ENOTCONN	57	/* Transport endpoint is not connected */
-#define	ESHUTDOWN	58	/* No send after transport endpoint shutdown */
-#define	ETOOMANYREFS	59	/* Too many references: cannot splice */
-#define	ETIMEDOUT	60	/* Connection timed out */
-#define	ECONNREFUSED	61	/* Connection refused */
-#define	ELOOP		62	/* Too many symbolic links encountered */
-#define	ENAMETOOLONG	63	/* File name too long */
-#define	EHOSTDOWN	64	/* Host is down */
-#define	EHOSTUNREACH	65	/* No route to host */
-#define	ENOTEMPTY	66	/* Directory not empty */
-#define EPROCLIM        67      /* SUNOS: Too many processes */
-#define	EUSERS		68	/* Too many users */
-#define	EDQUOT		69	/* Quota exceeded */
-#define	ESTALE		70	/* Stale NFS file handle */
-#define	EREMOTE		71	/* Object is remote */
-#define	ENOSTR		72	/* Device not a stream */
-#define	ETIME		73	/* Timer expired */
-#define	ENOSR		74	/* Out of streams resources */
-#define	ENOMSG		75	/* No message of desired type */
-#define	EBADMSG		76	/* Not a data message */
-#define	EIDRM		77	/* Identifier removed */
-#define	EDEADLK		78	/* Resource deadlock would occur */
-#define	ENOLCK		79	/* No record locks available */
-#define	ENONET		80	/* Machine is not on the network */
-#define ERREMOTE        81      /* SunOS: Too many lvls of remote in path */
-#define	ENOLINK		82	/* Link has been severed */
-#define	EADV		83	/* Advertise error */
-#define	ESRMNT		84	/* Srmount error */
-#define	ECOMM		85      /* Communication error on send */
-#define	EPROTO		86	/* Protocol error */
-#define	EMULTIHOP	87	/* Multihop attempted */
-#define	EDOTDOT		88	/* RFS specific error */
-#define	EREMCHG		89	/* Remote address changed */
-#define	ENOSYS		90	/* Function not implemented */
-
-/* The rest have no SunOS equivalent. */
-#define	ESTRPIPE	91	/* Streams pipe error */
-#define	EOVERFLOW	92	/* Value too large for defined data type */
-#define	EBADFD		93	/* File descriptor in bad state */
-#define	ECHRNG		94	/* Channel number out of range */
-#define	EL2NSYNC	95	/* Level 2 not synchronized */
-#define	EL3HLT		96	/* Level 3 halted */
-#define	EL3RST		97	/* Level 3 reset */
-#define	ELNRNG		98	/* Link number out of range */
-#define	EUNATCH		99	/* Protocol driver not attached */
-#define	ENOCSI		100	/* No CSI structure available */
-#define	EL2HLT		101	/* Level 2 halted */
-#define	EBADE		102	/* Invalid exchange */
-#define	EBADR		103	/* Invalid request descriptor */
-#define	EXFULL		104	/* Exchange full */
-#define	ENOANO		105	/* No anode */
-#define	EBADRQC		106	/* Invalid request code */
-#define	EBADSLT		107	/* Invalid slot */
-#define	EDEADLOCK	108	/* File locking deadlock error */
-#define	EBFONT		109	/* Bad font file format */
-#define	ELIBEXEC	110	/* Cannot exec a shared library directly */
-#define	ENODATA		111	/* No data available */
-#define	ELIBBAD		112	/* Accessing a corrupted shared library */
-#define	ENOPKG		113	/* Package not installed */
-#define	ELIBACC		114	/* Can not access a needed shared library */
-#define	ENOTUNIQ	115	/* Name not unique on network */
-#define	ERESTART	116	/* Interrupted syscall should be restarted */
-#define	EUCLEAN		117	/* Structure needs cleaning */
-#define	ENOTNAM		118	/* Not a XENIX named type file */
-#define	ENAVAIL		119	/* No XENIX semaphores available */
-#define	EISNAM		120	/* Is a named type file */
-#define	EREMOTEIO	121	/* Remote I/O error */
-#define	EILSEQ		122	/* Illegal byte sequence */
-#define	ELIBMAX		123	/* Atmpt to link in too many shared libs */
-#define	ELIBSCN		124	/* .lib section in a.out corrupted */
-
-#define ENOMEDIUM       125     /* No medium found */
-#define EMEDIUMTYPE     126     /* Wrong medium type */
-#define	ECANCELED	127	/* Operation Cancelled */
-#define	ENOKEY		128	/* Required key not available */
-#define	EKEYEXPIRED	129	/* Key has expired */
-#define	EKEYREVOKED	130	/* Key has been revoked */
-#define	EKEYREJECTED	131	/* Key was rejected by service */
-
-/* for robust mutexes */
-#define	EOWNERDEAD	132	/* Owner died */
-#define	ENOTRECOVERABLE	133	/* State not recoverable */
-
-#endif /* !(_SPARC64_ERRNO_H) */
+#include <asm-sparc/errno.h>
diff --git a/include/asm-sparc64/fb.h b/include/asm-sparc64/fb.h
index 389012e5fbad..1c2ac5832f39 100644
--- a/include/asm-sparc64/fb.h
+++ b/include/asm-sparc64/fb.h
@@ -1,27 +1 @@
-#ifndef _ASM_FB_H_
-#define _ASM_FB_H_
-#include <linux/fb.h>
-#include <linux/fs.h>
-#include <asm/page.h>
-#include <asm/prom.h>
-
-static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
-				unsigned long off)
-{
-	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-}
-
-static inline int fb_is_primary_device(struct fb_info *info)
-{
-	struct device *dev = info->device;
-	struct device_node *node;
-
-	node = dev->archdata.prom_node;
-	if (node &&
-	    node == of_console_device)
-		return 1;
-
-	return 0;
-}
-
-#endif /* _ASM_FB_H_ */
+#include <asm-sparc/fb.h>
diff --git a/include/asm-sparc64/io.h b/include/asm-sparc64/io.h
index b6ece223562d..c299b853b5ba 100644
--- a/include/asm-sparc64/io.h
+++ b/include/asm-sparc64/io.h
@@ -16,7 +16,7 @@
 /* BIO layer definitions. */
 extern unsigned long kern_base, kern_size;
 #define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
-#define BIO_VMERGE_BOUNDARY	0
+#define BIO_VMERGE_BOUNDARY	8192
 
 static inline u8 _inb(unsigned long addr)
 {
diff --git a/include/asm-sparc64/iommu.h b/include/asm-sparc64/iommu.h
index 9eac6676caf1..46325ddee23b 100644
--- a/include/asm-sparc64/iommu.h
+++ b/include/asm-sparc64/iommu.h
@@ -26,6 +26,7 @@ struct iommu_arena {
 struct iommu {
 	spinlock_t		lock;
 	struct iommu_arena	arena;
+	void			(*flush_all)(struct iommu *);
 	iopte_t			*page_table;
 	u32			page_table_map_base;
 	unsigned long		iommu_control;
diff --git a/include/asm-sparc64/kprobes.h b/include/asm-sparc64/kprobes.h
index 5020eaf67c29..7237dd87663e 100644
--- a/include/asm-sparc64/kprobes.h
+++ b/include/asm-sparc64/kprobes.h
@@ -14,11 +14,15 @@ typedef u32 kprobe_opcode_t;
 
 #define arch_remove_kprobe(p)	do {} while (0)
 
+#define ARCH_SUPPORTS_KRETPROBES
+
 #define flush_insn_slot(p)		\
 do { 	flushi(&(p)->ainsn.insn[0]);	\
 	flushi(&(p)->ainsn.insn[1]);	\
 } while (0)
 
+void kretprobe_trampoline(void);
+
 /* Architecture specific copy of original instruction*/
 struct arch_specific_insn {
 	/* copy of the original instruction */
diff --git a/include/asm-sparc64/of_device.h b/include/asm-sparc64/of_device.h
index 46d69b3223c5..a769fdbe164a 100644
--- a/include/asm-sparc64/of_device.h
+++ b/include/asm-sparc64/of_device.h
@@ -1,38 +1 @@
-#ifndef _ASM_SPARC64_OF_DEVICE_H
-#define _ASM_SPARC64_OF_DEVICE_H
-#ifdef __KERNEL__
-
-#include <linux/device.h>
-#include <linux/of.h>
-#include <linux/mod_devicetable.h>
-#include <asm/openprom.h>
-
-/*
- * The of_device is a kind of "base class" that is a superset of
- * struct device for use by devices attached to an OF node and
- * probed using OF properties.
- */
-struct of_device
-{
-	struct device_node		*node;
-	struct device			dev;
-	struct resource			resource[PROMREG_MAX];
-	unsigned int			irqs[PROMINTR_MAX];
-	int				num_irqs;
-
-	void				*sysdata;
-
-	int				slot;
-	int				portid;
-	int				clock_freq;
-};
-
-extern void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name);
-extern void of_iounmap(struct resource *res, void __iomem *base, unsigned long size);
-
-/* These are just here during the transition */
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_SPARC64_OF_DEVICE_H */
+#include <asm-sparc/of_device.h>
diff --git a/include/asm-sparc64/of_platform.h b/include/asm-sparc64/of_platform.h
index f15cfa723916..78aa032b674c 100644
--- a/include/asm-sparc64/of_platform.h
+++ b/include/asm-sparc64/of_platform.h
@@ -22,9 +22,4 @@ extern struct bus_type sbus_bus_type;
 
 #define of_bus_type	of_platform_bus_type	/* for compatibility */
 
-extern struct of_device *of_platform_device_create(struct device_node *np,
-						   const char *bus_id,
-						   struct device *parent,
-						   struct bus_type *bus);
-
 #endif	/* _ASM_SPARC64_OF_PLATFORM_H */
diff --git a/include/asm-sparc64/prom.h b/include/asm-sparc64/prom.h
index 07843f9f05df..5fa166ee3ffa 100644
--- a/include/asm-sparc64/prom.h
+++ b/include/asm-sparc64/prom.h
@@ -1,103 +1 @@
-#ifndef _SPARC64_PROM_H
-#define _SPARC64_PROM_H
-#ifdef __KERNEL__
-
-/*
- * Definitions for talking to the Open Firmware PROM on
- * Power Macintosh computers.
- *
- * Copyright (C) 1996-2005 Paul Mackerras.
- *
- * Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp.
- * Updates for SPARC64 by David S. Miller
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-#include <linux/types.h>
-#include <linux/proc_fs.h>
-#include <asm/atomic.h>
-
-#define OF_ROOT_NODE_ADDR_CELLS_DEFAULT	2
-#define OF_ROOT_NODE_SIZE_CELLS_DEFAULT	1
-
-#define of_compat_cmp(s1, s2, l)	strncmp((s1), (s2), (l))
-#define of_prop_cmp(s1, s2)		strcasecmp((s1), (s2))
-#define of_node_cmp(s1, s2)		strcmp((s1), (s2))
-
-typedef u32 phandle;
-typedef u32 ihandle;
-
-struct property {
-	char	*name;
-	int	length;
-	void	*value;
-	struct property *next;
-	unsigned long _flags;
-	unsigned int unique_id;
-};
-
-struct of_irq_controller;
-struct device_node {
-	const char	*name;
-	const char	*type;
-	phandle	node;
-	char	*path_component_name;
-	char	*full_name;
-
-	struct	property *properties;
-	struct  property *deadprops; /* removed properties */
-	struct	device_node *parent;
-	struct	device_node *child;
-	struct	device_node *sibling;
-	struct	device_node *next;	/* next device of same type */
-	struct	device_node *allnext;	/* next in list of all nodes */
-	struct  proc_dir_entry *pde;	/* this node's proc directory */
-	struct  kref kref;
-	unsigned long _flags;
-	void	*data;
-	unsigned int unique_id;
-
-	struct of_irq_controller *irq_trans;
-};
-
-struct of_irq_controller {
-	unsigned int	(*irq_build)(struct device_node *, unsigned int, void *);
-	void		*data;
-};
-
-#define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
-#define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
-
-extern struct device_node *of_find_node_by_cpuid(int cpuid);
-extern int of_set_property(struct device_node *node, const char *name, void *val, int len);
-extern int of_getintprop_default(struct device_node *np,
-				 const char *name,
-				 int def);
-extern int of_find_in_proplist(const char *list, const char *match, int len);
-
-extern void prom_build_devicetree(void);
-
-/* Dummy ref counting routines - to be implemented later */
-static inline struct device_node *of_node_get(struct device_node *node)
-{
-	return node;
-}
-static inline void of_node_put(struct device_node *node)
-{
-}
-
-/*
- * NB:  This is here while we transition from using asm/prom.h
- * to linux/of.h
- */
-#include <linux/of.h>
-
-extern struct device_node *of_console_device;
-extern char *of_console_path;
-extern char *of_console_options;
-
-#endif /* __KERNEL__ */
-#endif /* _SPARC64_PROM_H */
+#include <asm-sparc/prom.h>