浏览代码

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.
  ...
Linus Torvalds 17 年之前
父节点
当前提交
bfc1de0c40
共有 44 个文件被更改,包括 689 次插入1324 次删除
  1. 11 0
      Documentation/feature-removal-schedule.txt
  2. 6 138
      arch/sparc/kernel/errtbls.c
  3. 0 27
      arch/sparc/kernel/of_device.c
  4. 4 0
      arch/sparc/kernel/vmlinux.lds.S
  5. 4 0
      arch/sparc64/Kconfig
  6. 237 115
      arch/sparc64/kernel/iommu.c
  7. 13 20
      arch/sparc64/kernel/iommu_common.h
  8. 111 2
      arch/sparc64/kernel/kprobes.c
  9. 0 26
      arch/sparc64/kernel/of_device.c
  10. 144 134
      arch/sparc64/kernel/pci_sun4v.c
  11. 19 12
      include/asm-sparc/a.out.h
  12. 1 1
      include/asm-sparc/bpp.h
  13. 0 94
      include/asm-sparc/bsderrno.h
  14. 3 15
      include/asm-sparc/bug.h
  15. 13 5
      include/asm-sparc/bugs.h
  16. 47 4
      include/asm-sparc/byteorder.h
  17. 15 6
      include/asm-sparc/cache.h
  18. 17 14
      include/asm-sparc/current.h
  19. 0 2
      include/asm-sparc/device.h
  20. 0 1
      include/asm-sparc/errno.h
  21. 12 4
      include/asm-sparc/fb.h
  22. 0 5
      include/asm-sparc/of_platform.h
  23. 10 1
      include/asm-sparc/prom.h
  24. 1 98
      include/asm-sparc64/a.out.h
  25. 1 4
      include/asm-sparc64/auxvec.h
  26. 1 73
      include/asm-sparc64/bpp.h
  27. 0 94
      include/asm-sparc64/bsderrno.h
  28. 1 22
      include/asm-sparc64/bug.h
  29. 1 10
      include/asm-sparc64/bugs.h
  30. 1 49
      include/asm-sparc64/byteorder.h
  31. 1 18
      include/asm-sparc64/cache.h
  32. 1 6
      include/asm-sparc64/cputime.h
  33. 1 8
      include/asm-sparc64/current.h
  34. 1 21
      include/asm-sparc64/device.h
  35. 1 1
      include/asm-sparc64/div64.h
  36. 1 6
      include/asm-sparc64/emergency-restart.h
  37. 1 114
      include/asm-sparc64/errno.h
  38. 1 27
      include/asm-sparc64/fb.h
  39. 1 1
      include/asm-sparc64/io.h
  40. 1 0
      include/asm-sparc64/iommu.h
  41. 4 0
      include/asm-sparc64/kprobes.h
  42. 1 38
      include/asm-sparc64/of_device.h
  43. 0 5
      include/asm-sparc64/of_platform.h
  44. 1 103
      include/asm-sparc64/prom.h

+ 11 - 0
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
 	and slightly hurts runtime performance. Bugfixes for the old firmware
 	are not provided by Broadcom anymore.
 	are not provided by Broadcom anymore.
 Who:	Michael Buesch <mb@bu3sch.de>
 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>

+ 6 - 138
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:
  * Based upon preliminary work which is:
  *
  *
  * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
  * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu)
  */
  */
 
 
-#include <asm/bsderrno.h>        /* NetBSD (bsd4.4) errnos */
 #include <asm/solerrno.h>        /* Solaris 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[] = {
 int solaris_errno[] = {
@@ -145,132 +142,3 @@ int solaris_errno[] = {
 	SOL_ELIBMAX,
 	SOL_ELIBMAX,
 	SOL_ELIBSCN,
 	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,
-};
-

+ 0 - 27
arch/sparc/kernel/of_device.c

@@ -584,30 +584,3 @@ static int __init of_debug(char *str)
 }
 }
 
 
 __setup("of_debug=", of_debug);
 __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);

+ 4 - 0
arch/sparc/kernel/vmlinux.lds.S

@@ -89,6 +89,10 @@ SECTIONS
 	.data.cacheline_aligned : {
 	.data.cacheline_aligned : {
 		*(.data.cacheline_aligned)
 		*(.data.cacheline_aligned)
 	}
 	}
+	. = ALIGN(32);
+	.data.read_mostly : {
+		*(.data.read_mostly)
+	}
 
 
 	__bss_start = .;
 	__bss_start = .;
 	.sbss : {
 	.sbss : {

+ 4 - 0
arch/sparc64/Kconfig

@@ -41,6 +41,10 @@ config MMU
 	bool
 	bool
 	default y
 	default y
 
 
+config IOMMU_HELPER
+	bool
+	default y
+
 config QUICKLIST
 config QUICKLIST
 	bool
 	bool
 	default y
 	default y

+ 237 - 115
arch/sparc64/kernel/iommu.c

@@ -1,6 +1,6 @@
 /* iommu.c: Generic sparc64 IOMMU support.
 /* 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)
  * Copyright (C) 1999, 2000 Jakub Jelinek (jakub@redhat.com)
  */
  */
 
 
@@ -10,6 +10,7 @@
 #include <linux/device.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
 #include <linux/dma-mapping.h>
 #include <linux/errno.h>
 #include <linux/errno.h>
+#include <linux/iommu-helper.h>
 
 
 #ifdef CONFIG_PCI
 #ifdef CONFIG_PCI
 #include <linux/pci.h>
 #include <linux/pci.h>
@@ -41,7 +42,7 @@
 			       "i" (ASI_PHYS_BYPASS_EC_E))
 			       "i" (ASI_PHYS_BYPASS_EC_E))
 
 
 /* Must be invoked under the IOMMU lock. */
 /* 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) {
 	if (iommu->iommu_flushinv) {
 		iommu_write(iommu->iommu_flushinv, ~(u64)0);
 		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;
 	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;
 	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;
 	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)) {
 		if (likely(pass < 1)) {
-			limit = start;
+			/* First failure, rescan from the beginning.  */
 			start = 0;
 			start = 0;
-			__iommu_flushall(iommu);
+			if (iommu->flush_all)
+				iommu->flush_all(iommu);
 			pass++;
 			pass++;
 			goto again;
 			goto again;
 		} else {
 		} 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;
 	arena->hint = end;
 
 
+	/* Update handle for SG allocations */
+	if (handle)
+		*handle = end;
+
 	return n;
 	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,
 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;
 	iommu->arena.limit = num_tsb_entries;
 
 
+	if (tlb_type != hypervisor)
+		iommu->flush_all = iommu_flushall;
+
 	/* Allocate and initialize the dummy page which we
 	/* Allocate and initialize the dummy page which we
 	 * set inactive IO PTEs to point to.
 	 * set inactive IO PTEs to point to.
 	 */
 	 */
@@ -192,22 +233,18 @@ out_free_map:
 	return -ENOMEM;
 	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 NULL;
 
 
 	return iommu->page_table + entry;
 	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)
 static int iommu_alloc_ctx(struct iommu *iommu)
 {
 {
 	int lowest = iommu->ctx_lowest_free;
 	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;
 	iommu = dev->archdata.iommu;
 
 
 	spin_lock_irqsave(&iommu->lock, flags);
 	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);
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
 
 	if (unlikely(iopte == NULL)) {
 	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);
 	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);
 	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;
 	npages >>= IO_PAGE_SHIFT;
 
 
 	spin_lock_irqsave(&iommu->lock, flags);
 	spin_lock_irqsave(&iommu->lock, flags);
-	base = alloc_npages(iommu, npages);
+	base = alloc_npages(dev, iommu, npages);
 	ctx = 0;
 	ctx = 0;
 	if (iommu->iommu_ctxflush)
 	if (iommu->iommu_ctxflush)
 		ctx = iommu_alloc_ctx(iommu);
 		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++)
 	for (i = 0; i < npages; i++)
 		iopte_make_dummy(iommu, base + 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);
 	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,
 static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
 			 int nelems, enum dma_data_direction direction)
 			 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 strbuf *strbuf;
 	struct iommu *iommu;
 	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;
 	iommu = dev->archdata.iommu;
 	strbuf = dev->archdata.stc;
 	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);
 	spin_lock_irqsave(&iommu->lock, flags);
 
 
-	base = alloc_npages(iommu, npages);
 	ctx = 0;
 	ctx = 0;
 	if (iommu->iommu_ctxflush)
 	if (iommu->iommu_ctxflush)
 		ctx = iommu_alloc_ctx(iommu);
 		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)
 	if (strbuf->strbuf_enabled)
-		iopte_protection = IOPTE_STREAMING(ctx);
+		prot = IOPTE_STREAMING(ctx);
 	else
 	else
-		iopte_protection = IOPTE_CONSISTENT(ctx);
+		prot = IOPTE_CONSISTENT(ctx);
 	if (direction != DMA_TO_DEVICE)
 	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;
 		paddr &= IO_PAGE_MASK;
-		while (this_npages--) {
-			iopte_val(*base) = iopte_protection | paddr;
-
+		while (npages--) {
+			iopte_val(*base) = prot | paddr;
 			base++;
 			base++;
 			paddr += IO_PAGE_SIZE;
 			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;
 	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,
 static void dma_4u_unmap_sg(struct device *dev, struct scatterlist *sglist,
 			    int nelems, enum dma_data_direction direction)
 			    int nelems, enum dma_data_direction direction)
 {
 {
-	unsigned long flags, ctx, i, npages;
+	unsigned long flags, ctx;
+	struct scatterlist *sg;
 	struct strbuf *strbuf;
 	struct strbuf *strbuf;
 	struct iommu *iommu;
 	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;
 	iommu = dev->archdata.iommu;
 	strbuf = dev->archdata.stc;
 	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);
 	iommu_free_ctx(iommu, ctx);
 
 

+ 13 - 20
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/kernel.h>
 #include <linux/types.h>
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <linux/sched.h>
@@ -56,21 +58,12 @@ static inline unsigned long calc_npages(struct scatterlist *sglist, int nelems)
 	return npages;
 	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 */

+ 111 - 2
arch/sparc64/kernel/kprobes.c

@@ -480,8 +480,117 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
 	return 0;
 	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;
 	return 0;
 }
 }

+ 0 - 26
arch/sparc64/kernel/of_device.c

@@ -868,29 +868,3 @@ static int __init of_debug(char *str)
 }
 }
 
 
 __setup("of_debug=", of_debug);
 __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);

+ 144 - 134
arch/sparc64/kernel/pci_sun4v.c

@@ -1,6 +1,6 @@
 /* pci_sun4v.c: SUN4V specific PCI controller support.
 /* 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>
 #include <linux/kernel.h>
@@ -89,6 +89,17 @@ static long iommu_batch_flush(struct iommu_batch *p)
 	return 0;
 	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.  */
 /* Interrupts must be disabled.  */
 static inline long iommu_batch_add(u64 phys_page)
 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);
 	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,
 static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
 				   dma_addr_t *dma_addrp, gfp_t gfp)
 				   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;
 	iommu = dev->archdata.iommu;
 
 
 	spin_lock_irqsave(&iommu->lock, flags);
 	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);
 	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 +
 	*dma_addrp = (iommu->page_table_map_base +
 		      (entry << IO_PAGE_SHIFT));
 		      (entry << IO_PAGE_SHIFT));
@@ -219,10 +182,10 @@ static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
 iommu_map_fail:
 iommu_map_fail:
 	/* Interrupts are disabled.  */
 	/* Interrupts are disabled.  */
 	spin_lock(&iommu->lock);
 	spin_lock(&iommu->lock);
-	arena_free(&iommu->arena, entry, npages);
+	iommu_range_free(iommu, *dma_addrp, npages);
 	spin_unlock_irqrestore(&iommu->lock, flags);
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
 
-arena_alloc_fail:
+range_alloc_fail:
 	free_pages(first_page, order);
 	free_pages(first_page, order);
 	return NULL;
 	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);
 	spin_lock_irqsave(&iommu->lock, flags);
 
 
-	arena_free(&iommu->arena, entry, npages);
+	iommu_range_free(iommu, dvma, npages);
 
 
 	do {
 	do {
 		unsigned long num;
 		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;
 	npages >>= IO_PAGE_SHIFT;
 
 
 	spin_lock_irqsave(&iommu->lock, flags);
 	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);
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
 
-	if (unlikely(entry < 0L))
+	if (unlikely(entry == DMA_ERROR_CODE))
 		goto bad;
 		goto bad;
 
 
 	bus_addr = (iommu->page_table_map_base +
 	bus_addr = (iommu->page_table_map_base +
@@ -319,7 +282,7 @@ bad:
 iommu_map_fail:
 iommu_map_fail:
 	/* Interrupts are disabled.  */
 	/* Interrupts are disabled.  */
 	spin_lock(&iommu->lock);
 	spin_lock(&iommu->lock);
-	arena_free(&iommu->arena, entry, npages);
+	iommu_range_free(iommu, bus_addr, npages);
 	spin_unlock_irqrestore(&iommu->lock, flags);
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
 
 	return DMA_ERROR_CODE;
 	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);
 	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 {
 	do {
 		unsigned long num;
 		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,
 static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
 			 int nelems, enum dma_data_direction direction)
 			 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;
 	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;
 	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;
 		paddr &= IO_PAGE_MASK;
-		while (this_npages--) {
+		while (npages--) {
 			err = iommu_batch_add(paddr);
 			err = iommu_batch_add(paddr);
-			if (unlikely(err < 0L)) {
-				local_irq_restore(flags);
+			if (unlikely(err < 0L))
 				goto iommu_map_failed;
 				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();
 	err = iommu_batch_end();
 
 
-	local_irq_restore(flags);
-
 	if (unlikely(err < 0L))
 	if (unlikely(err < 0L))
 		goto iommu_map_failed;
 		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:
 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);
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
 
 	return 0;
 	return 0;
@@ -458,39 +464,43 @@ iommu_map_failed:
 static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist,
 static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist,
 			    int nelems, enum dma_data_direction direction)
 			    int nelems, enum dma_data_direction direction)
 {
 {
-	unsigned long flags, npages;
 	struct pci_pbm_info *pbm;
 	struct pci_pbm_info *pbm;
-	u32 devhandle, bus_addr;
+	struct scatterlist *sg;
 	struct iommu *iommu;
 	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;
 	iommu = dev->archdata.iommu;
 	pbm = dev->archdata.host_controller;
 	pbm = dev->archdata.host_controller;
 	devhandle = pbm->devhandle;
 	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);
 	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);
 	spin_unlock_irqrestore(&iommu->lock, flags);
 }
 }

+ 19 - 12
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__
 #ifndef __SPARC_A_OUT_H__
 #define __SPARC_A_OUT_H__
 #define __SPARC_A_OUT_H__
 
 
 #define SPARC_PGSIZE    0x2000        /* Thanks to the sun4 architecture... */
 #define SPARC_PGSIZE    0x2000        /* Thanks to the sun4 architecture... */
 #define SEGMENT_SIZE    SPARC_PGSIZE  /* whee... */
 #define SEGMENT_SIZE    SPARC_PGSIZE  /* whee... */
 
 
+#ifndef __ASSEMBLY__
+
 struct exec {
 struct exec {
 	unsigned char a_dynamic:1;      /* A __DYNAMIC is in this image */
 	unsigned char a_dynamic:1;      /* A __DYNAMIC is in this image */
 	unsigned char a_toolversion:7;
 	unsigned char a_toolversion:7;
 	unsigned char a_machtype;
 	unsigned char a_machtype;
 	unsigned short a_info;
 	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? */
 /* Where in the file does the text information begin? */
 #define N_TXTOFF(x)     (N_MAGIC(x) == ZMAGIC ? 0 : sizeof (struct exec))
 #define N_TXTOFF(x)     (N_MAGIC(x) == ZMAGIC ? 0 : sizeof (struct exec))
 
 
@@ -28,19 +31,21 @@ struct exec {
                          (x).a_drsize)
                          (x).a_drsize)
 
 
 /* Where does text segment go in memory after being loaded? */
 /* 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)) ?   \
 	                 ((x).a_entry < SPARC_PGSIZE)) ?   \
                           0 : SPARC_PGSIZE)
                           0 : SPARC_PGSIZE)
 
 
 /* And same for the data segment.. */
 /* And same for the data segment.. */
 #define N_DATADDR(x) (N_MAGIC(x)==OMAGIC ?         \
 #define N_DATADDR(x) (N_MAGIC(x)==OMAGIC ?         \
                       (N_TXTADDR(x) + (x).a_text)  \
                       (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_TRSIZE(a)	((a).a_trsize)
 #define N_DRSIZE(a)	((a).a_drsize)
 #define N_DRSIZE(a)	((a).a_drsize)
 #define N_SYMSIZE(a)	((a).a_syms)
 #define N_SYMSIZE(a)	((a).a_syms)
 
 
+#ifndef __ASSEMBLY__
+
 /*
 /*
  * Sparc relocation types
  * Sparc relocation types
  */
  */
@@ -77,14 +82,16 @@ enum reloc_type
  */
  */
 struct relocation_info /* used when header.a_machtype == M_SPARC */
 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_index:24; /* segment index or symbol index */
         unsigned int    r_extern:1; /* if F, r_index==SEG#; if T, SYM idx */
         unsigned int    r_extern:1; /* if F, r_index==SEG#; if T, SYM idx */
         unsigned int    r_pad:2;    /* <unused> */
         unsigned int    r_pad:2;    /* <unused> */
         enum reloc_type r_type:5;   /* type of relocation to perform */
         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
 #define N_RELOCATION_INFO_DECLARED 1
 
 
+#endif /* !(__ASSEMBLY__) */
+
 #endif /* __SPARC_A_OUT_H__ */
 #endif /* __SPARC_A_OUT_H__ */

+ 1 - 1
include/asm-sparc/bpp.h

@@ -17,7 +17,7 @@
  * with compliant or compatible devices. It will use whatever features
  * with compliant or compatible devices. It will use whatever features
  * the device supports, prefering those that are typically faster.
  * 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
  * writes work like any printer device. The driver only attempt to
  * negotiate 1284 modes when needed so that plugs can be pulled,
  * negotiate 1284 modes when needed so that plugs can be pulled,
  * switch boxes switched, etc., without disrupting things. It will
  * switch boxes switched, etc., without disrupting things. It will

+ 0 - 94
include/asm-sparc/bsderrno.h

@@ -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) */

+ 3 - 15
include/asm-sparc/bug.h

@@ -2,28 +2,16 @@
 #define _SPARC_BUG_H
 #define _SPARC_BUG_H
 
 
 #ifdef CONFIG_BUG
 #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
 #ifdef CONFIG_DEBUG_BUGVERBOSE
 extern void do_BUG(const char *file, int line);
 extern void do_BUG(const char *file, int line);
 #define BUG() do {					\
 #define BUG() do {					\
 	do_BUG(__FILE__, __LINE__);			\
 	do_BUG(__FILE__, __LINE__);			\
-	__bug_trap();				\
+	__builtin_trap();				\
 } while (0)
 } while (0)
 #else
 #else
-#define BUG()		__bug_trap()
+#define BUG()		__builtin_trap()
 #endif
 #endif
 
 
 #define HAVE_ARCH_BUG
 #define HAVE_ARCH_BUG

+ 13 - 5
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>
 #include <asm/cpudata.h>
+#endif
+
+#ifdef CONFIG_SPARC64
+#include <asm/sstate.h>
+#endif
 
 
 extern unsigned long loops_per_jiffy;
 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;
 	cpu_data(0).udelay_val = loops_per_jiffy;
 #endif
 #endif
+#ifdef CONFIG_SPARC64
+	sstate_running();
+#endif
 }
 }

+ 47 - 4
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
 #ifndef _SPARC_BYTEORDER_H
 #define _SPARC_BYTEORDER_H
 #define _SPARC_BYTEORDER_H
 
 
 #include <asm/types.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
 #endif
 
 
 #include <linux/byteorder/big_endian.h>
 #include <linux/byteorder/big_endian.h>

+ 15 - 6
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.
  *           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
 #ifndef _SPARC_CACHE_H
 #define _SPARC_CACHE_H
 #define _SPARC_CACHE_H
 
 
-#include <asm/asi.h>
-
 #define L1_CACHE_SHIFT 5
 #define L1_CACHE_SHIFT 5
 #define L1_CACHE_BYTES 32
 #define L1_CACHE_BYTES 32
 #define L1_CACHE_ALIGN(x) ((((x)+(L1_CACHE_BYTES-1))&~(L1_CACHE_BYTES-1)))
 #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
 /* Direct access to the instruction cache is provided through and
  * alternate address space.  The IDC bit must be off in the ICCR on
  * 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) :
 			     "r" (addr), "i" (ASI_M_FLUSH_USER) :
 			     "memory");
 			     "memory");
 }
 }
+#endif /* CONFIG_SPARC32 */
 
 
 #endif /* !(_SPARC_CACHE_H) */
 #endif /* !(_SPARC_CACHE_H) */

+ 17 - 14
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) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
  * Copyright (C) 2002 Pete Zaitcev (zaitcev@yahoo.com)
  * 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
  *  Derived from "include/asm-s390/current.h" by
  *  Martin Schwidefsky (schwidefsky@de.ibm.com)
  *  Martin Schwidefsky (schwidefsky@de.ibm.com)
  *  Derived from "include/asm-i386/current.h"
  *  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>
 #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)
 static inline struct task_struct *__get_current(void)
 {
 {
 	return current_thread_info()->task;
 	return current_thread_info()->task;
 }
 }
 #define current __get_current()
 #define current __get_current()
+#endif
 
 
-#endif /* !(_ASM_CURRENT_H) */
+#endif /* !(_SPARC_CURRENT_H) */

+ 0 - 2
include/asm-sparc/device.h

@@ -19,5 +19,3 @@ struct dev_archdata {
 };
 };
 
 
 #endif /* _ASM_SPARC_DEVICE_H */
 #endif /* _ASM_SPARC_DEVICE_H */
-
-

+ 0 - 1
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
 #ifndef _SPARC_ERRNO_H
 #define _SPARC_ERRNO_H
 #define _SPARC_ERRNO_H
 
 

+ 12 - 4
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/fb.h>
+#include <linux/fs.h>
+#include <asm/page.h>
 #include <asm/prom.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)
 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;
 	return 0;
 }
 }
 
 
-#endif /* _ASM_FB_H_ */
+#endif /* _SPARC_FB_H_ */

+ 0 - 5
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 */
 #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 */
 #endif	/* _ASM_SPARC_OF_PLATFORM_H */

+ 10 - 1
include/asm-sparc/prom.h

@@ -9,7 +9,7 @@
  * Copyright (C) 1996-2005 Paul Mackerras.
  * Copyright (C) 1996-2005 Paul Mackerras.
  *
  *
  * Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp.
  * 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
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * modify it under the terms of the GNU General Public License
@@ -39,6 +39,7 @@ struct property {
 	unsigned int unique_id;
 	unsigned int unique_id;
 };
 };
 
 
+struct of_irq_controller;
 struct device_node {
 struct device_node {
 	const char	*name;
 	const char	*name;
 	const char	*type;
 	const char	*type;
@@ -58,11 +59,19 @@ struct device_node {
 	unsigned long _flags;
 	unsigned long _flags;
 	void	*data;
 	void	*data;
 	unsigned int unique_id;
 	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_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
 #define OF_MARK_DYNAMIC(x) set_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_set_property(struct device_node *node, const char *name, void *val, int len);
 extern int of_getintprop_default(struct device_node *np,
 extern int of_getintprop_default(struct device_node *np,
 				 const char *name,
 				 const char *name,

+ 1 - 98
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>

+ 1 - 4
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>

+ 1 - 73
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>

+ 0 - 94
include/asm-sparc64/bsderrno.h

@@ -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) */

+ 1 - 22
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>

+ 1 - 10
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>

+ 1 - 49
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>

+ 1 - 18
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>

+ 1 - 6
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>

+ 1 - 8
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>

+ 1 - 21
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>

+ 1 - 1
include/asm-sparc64/div64.h

@@ -1 +1 @@
-#include <asm-generic/div64.h>
+#include <asm-sparc/div64.h>

+ 1 - 6
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>

+ 1 - 114
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>

+ 1 - 27
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>

+ 1 - 1
include/asm-sparc64/io.h

@@ -16,7 +16,7 @@
 /* BIO layer definitions. */
 /* BIO layer definitions. */
 extern unsigned long kern_base, kern_size;
 extern unsigned long kern_base, kern_size;
 #define page_to_phys(page)	(page_to_pfn(page) << PAGE_SHIFT)
 #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)
 static inline u8 _inb(unsigned long addr)
 {
 {

+ 1 - 0
include/asm-sparc64/iommu.h

@@ -26,6 +26,7 @@ struct iommu_arena {
 struct iommu {
 struct iommu {
 	spinlock_t		lock;
 	spinlock_t		lock;
 	struct iommu_arena	arena;
 	struct iommu_arena	arena;
+	void			(*flush_all)(struct iommu *);
 	iopte_t			*page_table;
 	iopte_t			*page_table;
 	u32			page_table_map_base;
 	u32			page_table_map_base;
 	unsigned long		iommu_control;
 	unsigned long		iommu_control;

+ 4 - 0
include/asm-sparc64/kprobes.h

@@ -14,11 +14,15 @@ typedef u32 kprobe_opcode_t;
 
 
 #define arch_remove_kprobe(p)	do {} while (0)
 #define arch_remove_kprobe(p)	do {} while (0)
 
 
+#define ARCH_SUPPORTS_KRETPROBES
+
 #define flush_insn_slot(p)		\
 #define flush_insn_slot(p)		\
 do { 	flushi(&(p)->ainsn.insn[0]);	\
 do { 	flushi(&(p)->ainsn.insn[0]);	\
 	flushi(&(p)->ainsn.insn[1]);	\
 	flushi(&(p)->ainsn.insn[1]);	\
 } while (0)
 } while (0)
 
 
+void kretprobe_trampoline(void);
+
 /* Architecture specific copy of original instruction*/
 /* Architecture specific copy of original instruction*/
 struct arch_specific_insn {
 struct arch_specific_insn {
 	/* copy of the original instruction */
 	/* copy of the original instruction */

+ 1 - 38
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>

+ 0 - 5
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 */
 #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 */
 #endif	/* _ASM_SPARC64_OF_PLATFORM_H */

+ 1 - 103
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>