ソースを参照

Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6

* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6:
  [SPARC64]: Fix show_stack() when stack argument is NULL.
  [SPARC]: Fix serial console node string creation.
  [SPARC]: Mark SBUS framebuffer ioctls as IGNORE in compat_ioctl.c
  [SPARC64]: asm-sparc64/floppy.h needs linux/pci.h
  [SPARC64]: Fix conflicts in SBUS/PCI/EBUS/ISA DMA handling.
  [VIDEO]: Fix OOPS in all SBUS framebuffer drivers.
  [SPARC64]: Handle mostek clock type in mini_rtc driver.
  [PARTITION]: Sun/Solaris VTOC table corrections
  [SPARC]: Fix floppy on some sun4c systems.
  [SPARC64]: Fix sun4u PCI config space accesses on sun4u.
  [PARTITION] MSDOS: Fix Sun num_partitions handling.
  [SPARC]: Update defconfig.
Linus Torvalds 18 年 前
コミット
9c837fb692

+ 40 - 146
arch/sparc/defconfig

@@ -1,12 +1,14 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.22-rc1
-# Mon May 14 03:25:14 2007
+# Linux kernel version: 2.6.23-rc1
+# Wed Jul 25 15:30:21 2007
 #
 CONFIG_MMU=y
 CONFIG_HIGHMEM=y
 CONFIG_ZONE_DMA=y
 CONFIG_GENERIC_ISA_DMA=y
+CONFIG_ARCH_NO_VIRT_TO_BUS=y
+CONFIG_OF=y
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
 
 #
@@ -23,12 +25,11 @@ CONFIG_LOCALVERSION=""
 CONFIG_LOCALVERSION_AUTO=y
 CONFIG_SWAP=y
 CONFIG_SYSVIPC=y
-# CONFIG_IPC_NS is not set
 CONFIG_SYSVIPC_SYSCTL=y
 CONFIG_POSIX_MQUEUE=y
 # CONFIG_BSD_PROCESS_ACCT is not set
 # CONFIG_TASKSTATS is not set
-# CONFIG_UTS_NS is not set
+# CONFIG_USER_NS is not set
 # CONFIG_AUDIT is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=14
@@ -63,24 +64,17 @@ CONFIG_SLAB=y
 CONFIG_RT_MUTEXES=y
 # CONFIG_TINY_SHMEM is not set
 CONFIG_BASE_SMALL=0
-
-#
-# Loadable module support
-#
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_MODULE_FORCE_UNLOAD is not set
 # CONFIG_MODVERSIONS is not set
 # CONFIG_MODULE_SRCVERSION_ALL is not set
 CONFIG_KMOD=y
-
-#
-# Block layer
-#
 CONFIG_BLOCK=y
 # CONFIG_LBD is not set
 # CONFIG_BLK_DEV_IO_TRACE is not set
 # CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
 
 #
 # IO Schedulers
@@ -113,11 +107,14 @@ CONFIG_GENERIC_CALIBRATE_DELAY=y
 CONFIG_ARCH_MAY_HAVE_PC_FDC=y
 # CONFIG_ARCH_HAS_ILOG2_U32 is not set
 # CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_EMULATED_CMPXCHG=y
 CONFIG_SUN_PM=y
 # CONFIG_SUN4 is not set
 CONFIG_PCI=y
+CONFIG_PCI_SYSCALL=y
 # CONFIG_ARCH_SUPPORTS_MSI is not set
 # CONFIG_PCI_DEBUG is not set
+# CONFIG_NO_DMA is not set
 CONFIG_SUN_OPENPROMFS=m
 # CONFIG_SPARC_LED is not set
 CONFIG_BINFMT_ELF=y
@@ -134,6 +131,7 @@ CONFIG_FLAT_NODE_MEM_MAP=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
 # CONFIG_RESOURCES_64BIT is not set
 CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
 
 #
 # Networking
@@ -197,25 +195,13 @@ CONFIG_IPV6_TUNNEL=m
 # CONFIG_IPV6_MULTIPLE_TABLES is not set
 # CONFIG_NETWORK_SECMARK is not set
 # CONFIG_NETFILTER is not set
-
-#
-# DCCP Configuration (EXPERIMENTAL)
-#
 # CONFIG_IP_DCCP is not set
-
-#
-# SCTP Configuration (EXPERIMENTAL)
-#
 CONFIG_IP_SCTP=m
 # CONFIG_SCTP_DBG_MSG is not set
 CONFIG_SCTP_DBG_OBJCNT=y
 # CONFIG_SCTP_HMAC_NONE is not set
 # CONFIG_SCTP_HMAC_SHA1 is not set
 CONFIG_SCTP_HMAC_MD5=y
-
-#
-# TIPC Configuration (EXPERIMENTAL)
-#
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
 # CONFIG_BRIDGE is not set
@@ -253,6 +239,7 @@ CONFIG_AF_RXRPC=m
 # CONFIG_MAC80211 is not set
 # CONFIG_IEEE80211 is not set
 # CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
 
 #
 # Device Drivers
@@ -267,28 +254,12 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y
 # CONFIG_DEBUG_DRIVER is not set
 # CONFIG_DEBUG_DEVRES is not set
 # CONFIG_SYS_HYPERVISOR is not set
-
-#
-# Connector - unified userspace <-> kernelspace linker
-#
 # CONFIG_CONNECTOR is not set
 # CONFIG_MTD is not set
-
-#
-# Parallel port support
-#
+CONFIG_OF_DEVICE=y
 # CONFIG_PARPORT is not set
-
-#
-# Plug and Play support
-#
-# CONFIG_PNPACPI is not set
-
-#
-# Block devices
-#
+CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_FD is not set
-# CONFIG_BLK_CPQ_DA is not set
 # CONFIG_BLK_CPQ_CISS_DA is not set
 # CONFIG_BLK_DEV_DAC960 is not set
 # CONFIG_BLK_DEV_UMEM is not set
@@ -303,18 +274,11 @@ CONFIG_BLK_DEV_RAM_SIZE=4096
 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
-
-#
-# Misc devices
-#
+CONFIG_MISC_DEVICES=y
 # CONFIG_PHANTOM is not set
+# CONFIG_EEPROM_93CX6 is not set
 # CONFIG_SGI_IOC4 is not set
 # CONFIG_TIFM_CORE is not set
-# CONFIG_BLINK is not set
-
-#
-# ATA/ATAPI/MFM/RLL support
-#
 # CONFIG_IDE is not set
 
 #
@@ -322,6 +286,7 @@ CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
 #
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
 # CONFIG_SCSI_TGT is not set
 # CONFIG_SCSI_NETLINK is not set
 CONFIG_SCSI_PROC_FS=y
@@ -352,12 +317,8 @@ CONFIG_SCSI_WAIT_SCAN=m
 CONFIG_SCSI_SPI_ATTRS=y
 # CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
-# CONFIG_SCSI_SAS_ATTRS is not set
 # CONFIG_SCSI_SAS_LIBSAS is not set
-
-#
-# SCSI low-level drivers
-#
+CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
 # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
 # CONFIG_SCSI_3W_9XXX is not set
@@ -367,7 +328,6 @@ CONFIG_SCSI_SPI_ATTRS=y
 # CONFIG_SCSI_AIC7XXX_OLD is not set
 # CONFIG_SCSI_AIC79XX is not set
 # CONFIG_SCSI_AIC94XX is not set
-# CONFIG_SCSI_DPT_I2O is not set
 # CONFIG_SCSI_ARCMSR is not set
 # CONFIG_MEGARAID_NEWGEN is not set
 # CONFIG_MEGARAID_LEGACY is not set
@@ -389,14 +349,9 @@ CONFIG_SCSI_QLOGICPTI=m
 # CONFIG_SCSI_DC390T is not set
 # CONFIG_SCSI_NSP32 is not set
 # CONFIG_SCSI_DEBUG is not set
-CONFIG_SCSI_ESP_CORE=y
 CONFIG_SCSI_SUNESP=y
 # CONFIG_SCSI_SRP is not set
 # CONFIG_ATA is not set
-
-#
-# Multi-device support (RAID and LVM)
-#
 # CONFIG_MD is not set
 
 #
@@ -412,30 +367,16 @@ CONFIG_SCSI_SUNESP=y
 #
 # CONFIG_FIREWIRE is not set
 # CONFIG_IEEE1394 is not set
-
-#
-# I2O device support
-#
 # CONFIG_I2O is not set
-
-#
-# Network device support
-#
 CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
 CONFIG_DUMMY=m
 # CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
 # CONFIG_EQUALIZER is not set
 CONFIG_TUN=m
-
-#
-# ARCnet devices
-#
 # CONFIG_ARCNET is not set
 # CONFIG_PHYLIB is not set
-
-#
-# Ethernet (10 or 100Mbit)
-#
 CONFIG_NET_ETHERNET=y
 CONFIG_MII=m
 CONFIG_SUNLANCE=y
@@ -445,10 +386,6 @@ CONFIG_SUNQE=m
 # CONFIG_SUNGEM is not set
 # CONFIG_CASSINI is not set
 # CONFIG_NET_VENDOR_3COM is not set
-
-#
-# Tulip family network device support
-#
 # CONFIG_NET_TULIP is not set
 # CONFIG_HP100 is not set
 # CONFIG_NET_PCI is not set
@@ -464,7 +401,7 @@ CONFIG_NETDEV_1000=y
 # CONFIG_SIS190 is not set
 # CONFIG_SKGE is not set
 # CONFIG_SKY2 is not set
-# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
 # CONFIG_TIGON3 is not set
 # CONFIG_BNX2 is not set
 # CONFIG_QLA3XXX is not set
@@ -477,11 +414,6 @@ CONFIG_NETDEV_10000=y
 # CONFIG_MYRI10GE is not set
 # CONFIG_NETXEN_NIC is not set
 # CONFIG_MLX4_CORE is not set
-CONFIG_MLX4_DEBUG=y
-
-#
-# Token Ring devices
-#
 # CONFIG_TR is not set
 
 #
@@ -499,15 +431,7 @@ CONFIG_MLX4_DEBUG=y
 # CONFIG_NETCONSOLE is not set
 # CONFIG_NETPOLL is not set
 # CONFIG_NET_POLL_CONTROLLER is not set
-
-#
-# ISDN subsystem
-#
 # CONFIG_ISDN is not set
-
-#
-# Telephony Support
-#
 # CONFIG_PHONE is not set
 
 #
@@ -515,6 +439,7 @@ CONFIG_MLX4_DEBUG=y
 #
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
 
 #
 # Userland interfaces
@@ -593,22 +518,13 @@ CONFIG_SERIAL_CORE_CONSOLE=y
 CONFIG_UNIX98_PTYS=y
 CONFIG_LEGACY_PTYS=y
 CONFIG_LEGACY_PTY_COUNT=256
-
-#
-# IPMI
-#
 # CONFIG_IPMI_HANDLER is not set
 # CONFIG_WATCHDOG is not set
 CONFIG_HW_RANDOM=m
 CONFIG_JS_RTC=m
 # CONFIG_R3964 is not set
 # CONFIG_APPLICOM is not set
-# CONFIG_DRM is not set
 # CONFIG_RAW_DRIVER is not set
-
-#
-# TPM devices
-#
 # CONFIG_TCG_TPM is not set
 CONFIG_DEVPORT=y
 # CONFIG_I2C is not set
@@ -618,20 +534,24 @@ CONFIG_DEVPORT=y
 #
 # CONFIG_SPI is not set
 # CONFIG_SPI_MASTER is not set
-
-#
-# Dallas's 1-wire bus
-#
 # CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
 CONFIG_HWMON=y
 # CONFIG_HWMON_VID is not set
 # CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ABITUGURU3 is not set
 # CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_PC87360 is not set
 # CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_SIS5595 is not set
 # CONFIG_SENSORS_SMSC47M1 is not set
 # CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_VIA686A is not set
 # CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
 # CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
 # CONFIG_HWMON_DEBUG_CHIP is not set
 
 #
@@ -656,6 +576,7 @@ CONFIG_HWMON=y
 #
 # CONFIG_DISPLAY_SUPPORT is not set
 # CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
 # CONFIG_FB is not set
 
 #
@@ -668,16 +589,10 @@ CONFIG_DUMMY_CONSOLE=y
 # Sound
 #
 # CONFIG_SOUND is not set
-
-#
-# HID Devices
-#
+CONFIG_HID_SUPPORT=y
 CONFIG_HID=y
 # CONFIG_HID_DEBUG is not set
-
-#
-# USB support
-#
+CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 CONFIG_USB_ARCH_HAS_OHCI=y
 CONFIG_USB_ARCH_HAS_EHCI=y
@@ -692,29 +607,9 @@ CONFIG_USB_ARCH_HAS_EHCI=y
 #
 # CONFIG_USB_GADGET is not set
 # CONFIG_MMC is not set
-
-#
-# LED devices
-#
 # CONFIG_NEW_LEDS is not set
-
-#
-# LED drivers
-#
-
-#
-# LED Triggers
-#
-
-#
-# InfiniBand support
-#
 # CONFIG_INFINIBAND is not set
 
-#
-# EDAC - error detection and reporting (RAS) (EXPERIMENTAL)
-#
-
 #
 # Real Time Clock
 #
@@ -733,6 +628,11 @@ CONFIG_USB_ARCH_HAS_EHCI=y
 # DMA Devices
 #
 
+#
+# Userspace I/O
+#
+# CONFIG_UIO is not set
+
 #
 # Misc Linux/SPARC drivers
 #
@@ -853,7 +753,6 @@ CONFIG_CIFS=m
 # CONFIG_CODA_FS is not set
 CONFIG_AFS_FS=m
 # CONFIG_AFS_DEBUG is not set
-# CONFIG_9P_FS is not set
 
 #
 # Partition Types
@@ -927,6 +826,7 @@ CONFIG_MAGIC_SYSRQ=y
 # CONFIG_HEADERS_CHECK is not set
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_SCHED_DEBUG is not set
 # CONFIG_SCHEDSTATS is not set
 # CONFIG_TIMER_STATS is not set
 # CONFIG_DEBUG_SLAB is not set
@@ -953,10 +853,6 @@ CONFIG_FORCED_INLINING=y
 CONFIG_KEYS=y
 # CONFIG_KEYS_DEBUG_PROC_KEYS is not set
 # CONFIG_SECURITY is not set
-
-#
-# Cryptographic options
-#
 CONFIG_CRYPTO=y
 CONFIG_CRYPTO_ALGAPI=y
 CONFIG_CRYPTO_BLKCIPHER=y
@@ -996,10 +892,7 @@ CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_CRC32C=m
 # CONFIG_CRYPTO_CAMELLIA is not set
 # CONFIG_CRYPTO_TEST is not set
-
-#
-# Hardware crypto devices
-#
+# CONFIG_CRYPTO_HW is not set
 
 #
 # Library routines
@@ -1009,6 +902,7 @@ CONFIG_BITREVERSE=y
 # CONFIG_CRC16 is not set
 # CONFIG_CRC_ITU_T is not set
 CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
 CONFIG_LIBCRC32C=m
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y

+ 3 - 2
arch/sparc/kernel/prom.c

@@ -415,7 +415,7 @@ static void __init of_console_init(void)
 	unsigned long flags;
 	const char *type;
 	phandle node;
-	int skip, fd;
+	int skip, tmp, fd;
 
 	of_console_path = prom_early_alloc(256);
 
@@ -442,8 +442,9 @@ static void __init of_console_init(void)
 			prom_halt();
 		}
 
+		tmp = skip;
 		for_each_node_by_type(dp, type) {
-			if (!skip--)
+			if (!tmp--)
 				break;
 		}
 		if (!dp) {

+ 2 - 2
arch/sparc64/kernel/Makefile

@@ -8,14 +8,14 @@ EXTRA_CFLAGS := -Werror
 extra-y		:= head.o init_task.o vmlinux.lds
 
 obj-y		:= process.o setup.o cpu.o idprom.o \
-		   traps.o auxio.o una_asm.o sysfs.o \
+		   traps.o auxio.o una_asm.o sysfs.o iommu.o \
 		   irq.o ptrace.o time.o sys_sparc.o signal.o \
 		   unaligned.o central.o pci.o starfire.o semaphore.o \
 		   power.o sbus.o iommu_common.o sparc64_ksyms.o chmc.o \
 		   visemul.o prom.o of_device.o hvapi.o sstate.o mdesc.o
 
 obj-$(CONFIG_STACKTRACE) += stacktrace.o
-obj-$(CONFIG_PCI)	 += ebus.o isa.o pci_common.o pci_iommu.o \
+obj-$(CONFIG_PCI)	 += ebus.o isa.o pci_common.o \
 			    pci_psycho.o pci_sabre.o pci_schizo.o \
 			    pci_sun4v.o pci_sun4v_asm.o pci_fire.o
 obj-$(CONFIG_SMP)	 += smp.o trampoline.o hvtramp.o

+ 2 - 0
arch/sparc64/kernel/ebus.c

@@ -391,6 +391,8 @@ static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_de
 	sd = &dev->ofdev.dev.archdata;
 	sd->prom_node = dp;
 	sd->op = &dev->ofdev;
+	sd->iommu = dev->bus->ofdev.dev.parent->archdata.iommu;
+	sd->stc = dev->bus->ofdev.dev.parent->archdata.stc;
 
 	dev->ofdev.node = dp;
 	dev->ofdev.dev.parent = &dev->bus->ofdev.dev;

+ 145 - 159
arch/sparc64/kernel/pci_iommu.c → arch/sparc64/kernel/iommu.c

@@ -1,28 +1,32 @@
-/* pci_iommu.c: UltraSparc PCI controller IOM/STC support.
+/* iommu.c: Generic sparc64 IOMMU support.
  *
  * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net)
  * Copyright (C) 1999, 2000 Jakub Jelinek (jakub@redhat.com)
  */
 
 #include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
+#include <linux/module.h>
 #include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+
+#ifdef CONFIG_PCI
 #include <linux/pci.h>
+#endif
 
-#include <asm/oplib.h>
+#include <asm/iommu.h>
 
 #include "iommu_common.h"
-#include "pci_impl.h"
 
-#define PCI_STC_CTXMATCH_ADDR(STC, CTX)	\
+#define STC_CTXMATCH_ADDR(STC, CTX)	\
 	((STC)->strbuf_ctxmatch_base + ((CTX) << 3))
+#define STC_FLUSHFLAG_INIT(STC) \
+	(*((STC)->strbuf_flushflag) = 0UL)
+#define STC_FLUSHFLAG_SET(STC) \
+	(*((STC)->strbuf_flushflag) != 0UL)
 
-/* Accessing IOMMU and Streaming Buffer registers.
- * REG parameter is a physical address.  All registers
- * are 64-bits in size.
- */
-#define pci_iommu_read(__reg) \
+#define iommu_read(__reg) \
 ({	u64 __ret; \
 	__asm__ __volatile__("ldxa [%1] %2, %0" \
 			     : "=r" (__ret) \
@@ -30,7 +34,7 @@
 			     : "memory"); \
 	__ret; \
 })
-#define pci_iommu_write(__reg, __val) \
+#define iommu_write(__reg, __val) \
 	__asm__ __volatile__("stxa %0, [%1] %2" \
 			     : /* no outputs */ \
 			     : "r" (__val), "r" (__reg), \
@@ -40,19 +44,19 @@
 static void __iommu_flushall(struct iommu *iommu)
 {
 	if (iommu->iommu_flushinv) {
-		pci_iommu_write(iommu->iommu_flushinv, ~(u64)0);
+		iommu_write(iommu->iommu_flushinv, ~(u64)0);
 	} else {
 		unsigned long tag;
 		int entry;
 
-		tag = iommu->iommu_flush + (0xa580UL - 0x0210UL);
+		tag = iommu->iommu_tags;
 		for (entry = 0; entry < 16; entry++) {
-			pci_iommu_write(tag, 0);
+			iommu_write(tag, 0);
 			tag += 8;
 		}
 
 		/* Ensure completion of previous PIO writes. */
-		(void) pci_iommu_read(iommu->write_complete_reg);
+		(void) iommu_read(iommu->write_complete_reg);
 	}
 }
 
@@ -80,7 +84,7 @@ static inline void iopte_make_dummy(struct iommu *iommu, iopte_t *iopte)
 }
 
 /* Based largely upon the ppc64 iommu allocator.  */
-static long pci_arena_alloc(struct iommu *iommu, unsigned long npages)
+static long arena_alloc(struct iommu *iommu, unsigned long npages)
 {
 	struct iommu_arena *arena = &iommu->arena;
 	unsigned long n, i, start, end, limit;
@@ -121,7 +125,7 @@ again:
 	return n;
 }
 
-static void pci_arena_free(struct iommu_arena *arena, unsigned long base, unsigned long npages)
+static void arena_free(struct iommu_arena *arena, unsigned long base, unsigned long npages)
 {
 	unsigned long i;
 
@@ -129,7 +133,8 @@ static void pci_arena_free(struct iommu_arena *arena, unsigned long base, unsign
 		__clear_bit(i, arena->map);
 }
 
-void pci_iommu_table_init(struct iommu *iommu, int tsbsize, u32 dma_offset, u32 dma_addr_mask)
+int iommu_table_init(struct iommu *iommu, int tsbsize,
+		     u32 dma_offset, u32 dma_addr_mask)
 {
 	unsigned long i, tsbbase, order, sz, num_tsb_entries;
 
@@ -146,8 +151,8 @@ void pci_iommu_table_init(struct iommu *iommu, int tsbsize, u32 dma_offset, u32
 	sz = (sz + 7UL) & ~7UL;
 	iommu->arena.map = kzalloc(sz, GFP_KERNEL);
 	if (!iommu->arena.map) {
-		prom_printf("PCI_IOMMU: Error, kmalloc(arena.map) failed.\n");
-		prom_halt();
+		printk(KERN_ERR "IOMMU: Error, kmalloc(arena.map) failed.\n");
+		return -ENOMEM;
 	}
 	iommu->arena.limit = num_tsb_entries;
 
@@ -156,8 +161,8 @@ void pci_iommu_table_init(struct iommu *iommu, int tsbsize, u32 dma_offset, u32
 	 */
 	iommu->dummy_page = __get_free_pages(GFP_KERNEL, 0);
 	if (!iommu->dummy_page) {
-		prom_printf("PCI_IOMMU: Error, gfp(dummy_page) failed.\n");
-		prom_halt();
+		printk(KERN_ERR "IOMMU: Error, gfp(dummy_page) failed.\n");
+		goto out_free_map;
 	}
 	memset((void *)iommu->dummy_page, 0, PAGE_SIZE);
 	iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page);
@@ -166,20 +171,32 @@ void pci_iommu_table_init(struct iommu *iommu, int tsbsize, u32 dma_offset, u32
 	order = get_order(tsbsize);
 	tsbbase = __get_free_pages(GFP_KERNEL, order);
 	if (!tsbbase) {
-		prom_printf("PCI_IOMMU: Error, gfp(tsb) failed.\n");
-		prom_halt();
+		printk(KERN_ERR "IOMMU: Error, gfp(tsb) failed.\n");
+		goto out_free_dummy_page;
 	}
 	iommu->page_table = (iopte_t *)tsbbase;
 
 	for (i = 0; i < num_tsb_entries; i++)
 		iopte_make_dummy(iommu, &iommu->page_table[i]);
+
+	return 0;
+
+out_free_dummy_page:
+	free_page(iommu->dummy_page);
+	iommu->dummy_page = 0UL;
+
+out_free_map:
+	kfree(iommu->arena.map);
+	iommu->arena.map = NULL;
+
+	return -ENOMEM;
 }
 
 static inline iopte_t *alloc_npages(struct iommu *iommu, unsigned long npages)
 {
 	long entry;
 
-	entry = pci_arena_alloc(iommu, npages);
+	entry = arena_alloc(iommu, npages);
 	if (unlikely(entry < 0))
 		return NULL;
 
@@ -188,7 +205,7 @@ static inline iopte_t *alloc_npages(struct iommu *iommu, unsigned long npages)
 
 static inline void free_npages(struct iommu *iommu, dma_addr_t base, unsigned long npages)
 {
-	pci_arena_free(&iommu->arena, base >> IO_PAGE_SHIFT, npages);
+	arena_free(&iommu->arena, base >> IO_PAGE_SHIFT, npages);
 }
 
 static int iommu_alloc_ctx(struct iommu *iommu)
@@ -219,11 +236,8 @@ static inline void iommu_free_ctx(struct iommu *iommu, int ctx)
 	}
 }
 
-/* Allocate and map kernel buffer of size SIZE using consistent mode
- * DMA for PCI device PDEV.  Return non-NULL cpu-side address if
- * successful and set *DMA_ADDRP to the PCI side dma address.
- */
-static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp, gfp_t gfp)
+static void *dma_4u_alloc_coherent(struct device *dev, size_t size,
+				   dma_addr_t *dma_addrp, gfp_t gfp)
 {
 	struct iommu *iommu;
 	iopte_t *iopte;
@@ -241,7 +255,7 @@ static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
 		return NULL;
 	memset((char *)first_page, 0, PAGE_SIZE << order);
 
-	iommu = pdev->dev.archdata.iommu;
+	iommu = dev->archdata.iommu;
 
 	spin_lock_irqsave(&iommu->lock, flags);
 	iopte = alloc_npages(iommu, size >> IO_PAGE_SHIFT);
@@ -268,15 +282,15 @@ static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
 	return ret;
 }
 
-/* Free and unmap a consistent DMA translation. */
-static void pci_4u_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_t dvma)
+static void dma_4u_free_coherent(struct device *dev, size_t size,
+				 void *cpu, dma_addr_t dvma)
 {
 	struct iommu *iommu;
 	iopte_t *iopte;
 	unsigned long flags, order, npages;
 
 	npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT;
-	iommu = pdev->dev.archdata.iommu;
+	iommu = dev->archdata.iommu;
 	iopte = iommu->page_table +
 		((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
 
@@ -291,10 +305,8 @@ static void pci_4u_free_consistent(struct pci_dev *pdev, size_t size, void *cpu,
 		free_pages((unsigned long)cpu, order);
 }
 
-/* Map a single buffer at PTR of SZ bytes for PCI DMA
- * in streaming mode.
- */
-static dma_addr_t pci_4u_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direction)
+static dma_addr_t dma_4u_map_single(struct device *dev, void *ptr, size_t sz,
+				    enum dma_data_direction direction)
 {
 	struct iommu *iommu;
 	struct strbuf *strbuf;
@@ -304,10 +316,10 @@ static dma_addr_t pci_4u_map_single(struct pci_dev *pdev, void *ptr, size_t sz,
 	u32 bus_addr, ret;
 	unsigned long iopte_protection;
 
-	iommu = pdev->dev.archdata.iommu;
-	strbuf = pdev->dev.archdata.stc;
+	iommu = dev->archdata.iommu;
+	strbuf = dev->archdata.stc;
 
-	if (unlikely(direction == PCI_DMA_NONE))
+	if (unlikely(direction == DMA_NONE))
 		goto bad_no_ctx;
 
 	oaddr = (unsigned long)ptr;
@@ -332,7 +344,7 @@ static dma_addr_t pci_4u_map_single(struct pci_dev *pdev, void *ptr, size_t sz,
 		iopte_protection = IOPTE_STREAMING(ctx);
 	else
 		iopte_protection = IOPTE_CONSISTENT(ctx);
-	if (direction != PCI_DMA_TODEVICE)
+	if (direction != DMA_TO_DEVICE)
 		iopte_protection |= IOPTE_WRITE;
 
 	for (i = 0; i < npages; i++, base++, base_paddr += IO_PAGE_SIZE)
@@ -345,10 +357,12 @@ bad:
 bad_no_ctx:
 	if (printk_ratelimit())
 		WARN_ON(1);
-	return PCI_DMA_ERROR_CODE;
+	return DMA_ERROR_CODE;
 }
 
-static void pci_strbuf_flush(struct strbuf *strbuf, struct iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages, int direction)
+static void strbuf_flush(struct strbuf *strbuf, struct iommu *iommu,
+			 u32 vaddr, unsigned long ctx, unsigned long npages,
+			 enum dma_data_direction direction)
 {
 	int limit;
 
@@ -358,22 +372,22 @@ static void pci_strbuf_flush(struct strbuf *strbuf, struct iommu *iommu, u32 vad
 		u64 val;
 
 		flushreg = strbuf->strbuf_ctxflush;
-		matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
+		matchreg = STC_CTXMATCH_ADDR(strbuf, ctx);
 
-		pci_iommu_write(flushreg, ctx);
-		val = pci_iommu_read(matchreg);
+		iommu_write(flushreg, ctx);
+		val = iommu_read(matchreg);
 		val &= 0xffff;
 		if (!val)
 			goto do_flush_sync;
 
 		while (val) {
 			if (val & 0x1)
-				pci_iommu_write(flushreg, ctx);
+				iommu_write(flushreg, ctx);
 			val >>= 1;
 		}
-		val = pci_iommu_read(matchreg);
+		val = iommu_read(matchreg);
 		if (unlikely(val)) {
-			printk(KERN_WARNING "pci_strbuf_flush: ctx flush "
+			printk(KERN_WARNING "strbuf_flush: ctx flush "
 			       "timeout matchreg[%lx] ctx[%lx]\n",
 			       val, ctx);
 			goto do_page_flush;
@@ -383,7 +397,7 @@ static void pci_strbuf_flush(struct strbuf *strbuf, struct iommu *iommu, u32 vad
 
 	do_page_flush:
 		for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE)
-			pci_iommu_write(strbuf->strbuf_pflush, vaddr);
+			iommu_write(strbuf->strbuf_pflush, vaddr);
 	}
 
 do_flush_sync:
@@ -391,15 +405,15 @@ do_flush_sync:
 	 * the streaming cache, no flush-flag synchronization needs
 	 * to be performed.
 	 */
-	if (direction == PCI_DMA_TODEVICE)
+	if (direction == DMA_TO_DEVICE)
 		return;
 
-	PCI_STC_FLUSHFLAG_INIT(strbuf);
-	pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
-	(void) pci_iommu_read(iommu->write_complete_reg);
+	STC_FLUSHFLAG_INIT(strbuf);
+	iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
+	(void) iommu_read(iommu->write_complete_reg);
 
 	limit = 100000;
-	while (!PCI_STC_FLUSHFLAG_SET(strbuf)) {
+	while (!STC_FLUSHFLAG_SET(strbuf)) {
 		limit--;
 		if (!limit)
 			break;
@@ -407,37 +421,32 @@ do_flush_sync:
 		rmb();
 	}
 	if (!limit)
-		printk(KERN_WARNING "pci_strbuf_flush: flushflag timeout "
+		printk(KERN_WARNING "strbuf_flush: flushflag timeout "
 		       "vaddr[%08x] ctx[%lx] npages[%ld]\n",
 		       vaddr, ctx, npages);
 }
 
-/* Unmap a single streaming mode DMA translation. */
-static void pci_4u_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction)
+static void dma_4u_unmap_single(struct device *dev, dma_addr_t bus_addr,
+				size_t sz, enum dma_data_direction direction)
 {
 	struct iommu *iommu;
 	struct strbuf *strbuf;
 	iopte_t *base;
 	unsigned long flags, npages, ctx, i;
 
-	if (unlikely(direction == PCI_DMA_NONE)) {
+	if (unlikely(direction == DMA_NONE)) {
 		if (printk_ratelimit())
 			WARN_ON(1);
 		return;
 	}
 
-	iommu = pdev->dev.archdata.iommu;
-	strbuf = pdev->dev.archdata.stc;
+	iommu = dev->archdata.iommu;
+	strbuf = dev->archdata.stc;
 
 	npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK);
 	npages >>= IO_PAGE_SHIFT;
 	base = iommu->page_table +
 		((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
-#ifdef DEBUG_PCI_IOMMU
-	if (IOPTE_IS_DUMMY(iommu, base))
-		printk("pci_unmap_single called on non-mapped region %08x,%08x from %016lx\n",
-		       bus_addr, sz, __builtin_return_address(0));
-#endif
 	bus_addr &= IO_PAGE_MASK;
 
 	spin_lock_irqsave(&iommu->lock, flags);
@@ -449,8 +458,8 @@ static void pci_4u_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_
 
 	/* Step 1: Kick data out of streaming buffers if necessary. */
 	if (strbuf->strbuf_enabled)
-		pci_strbuf_flush(strbuf, iommu, bus_addr, ctx,
-				 npages, direction);
+		strbuf_flush(strbuf, iommu, bus_addr, ctx,
+			     npages, direction);
 
 	/* Step 2: Clear out TSB entries. */
 	for (i = 0; i < npages; i++)
@@ -467,7 +476,8 @@ static void pci_4u_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_
 	(__pa(page_address((SG)->page)) + (SG)->offset)
 
 static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg,
-			   int nused, int nelems, unsigned long iopte_protection)
+			   int nused, int nelems,
+			   unsigned long iopte_protection)
 {
 	struct scatterlist *dma_sg = sg;
 	struct scatterlist *sg_end = sg + nelems;
@@ -539,12 +549,8 @@ static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg,
 	}
 }
 
-/* Map a set of buffers described by SGLIST with NELEMS array
- * elements in streaming mode for PCI DMA.
- * When making changes here, inspect the assembly output. I was having
- * hard time to keep this routine out of using stack slots for holding variables.
- */
-static int pci_4u_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
+static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
+			 int nelems, enum dma_data_direction direction)
 {
 	struct iommu *iommu;
 	struct strbuf *strbuf;
@@ -557,19 +563,20 @@ static int pci_4u_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n
 	/* Fast path single entry scatterlists. */
 	if (nelems == 1) {
 		sglist->dma_address =
-			pci_4u_map_single(pdev,
-					  (page_address(sglist->page) + sglist->offset),
+			dma_4u_map_single(dev,
+					  (page_address(sglist->page) +
+					   sglist->offset),
 					  sglist->length, direction);
-		if (unlikely(sglist->dma_address == PCI_DMA_ERROR_CODE))
+		if (unlikely(sglist->dma_address == DMA_ERROR_CODE))
 			return 0;
 		sglist->dma_length = sglist->length;
 		return 1;
 	}
 
-	iommu = pdev->dev.archdata.iommu;
-	strbuf = pdev->dev.archdata.stc;
-	
-	if (unlikely(direction == PCI_DMA_NONE))
+	iommu = dev->archdata.iommu;
+	strbuf = dev->archdata.stc;
+
+	if (unlikely(direction == DMA_NONE))
 		goto bad_no_ctx;
 
 	/* Step 1: Prepare scatter list. */
@@ -609,7 +616,7 @@ static int pci_4u_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n
 		iopte_protection = IOPTE_STREAMING(ctx);
 	else
 		iopte_protection = IOPTE_CONSISTENT(ctx);
-	if (direction != PCI_DMA_TODEVICE)
+	if (direction != DMA_TO_DEVICE)
 		iopte_protection |= IOPTE_WRITE;
 
 	fill_sg(base, sglist, used, nelems, iopte_protection);
@@ -628,8 +635,8 @@ bad_no_ctx:
 	return 0;
 }
 
-/* Unmap a set of streaming mode DMA translations. */
-static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
+static void dma_4u_unmap_sg(struct device *dev, struct scatterlist *sglist,
+			    int nelems, enum dma_data_direction direction)
 {
 	struct iommu *iommu;
 	struct strbuf *strbuf;
@@ -637,14 +644,14 @@ static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in
 	unsigned long flags, ctx, i, npages;
 	u32 bus_addr;
 
-	if (unlikely(direction == PCI_DMA_NONE)) {
+	if (unlikely(direction == DMA_NONE)) {
 		if (printk_ratelimit())
 			WARN_ON(1);
 	}
 
-	iommu = pdev->dev.archdata.iommu;
-	strbuf = pdev->dev.archdata.stc;
-	
+	iommu = dev->archdata.iommu;
+	strbuf = dev->archdata.stc;
+
 	bus_addr = sglist->dma_address & IO_PAGE_MASK;
 
 	for (i = 1; i < nelems; i++)
@@ -657,11 +664,6 @@ static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in
 	base = iommu->page_table +
 		((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
 
-#ifdef DEBUG_PCI_IOMMU
-	if (IOPTE_IS_DUMMY(iommu, base))
-		printk("pci_unmap_sg called on non-mapped region %016lx,%d from %016lx\n", sglist->dma_address, nelems, __builtin_return_address(0));
-#endif
-
 	spin_lock_irqsave(&iommu->lock, flags);
 
 	/* Record the context, if any. */
@@ -671,7 +673,7 @@ static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in
 
 	/* Step 1: Kick data out of streaming buffers if necessary. */
 	if (strbuf->strbuf_enabled)
-		pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
+		strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
 
 	/* Step 2: Clear out the TSB entries. */
 	for (i = 0; i < npages; i++)
@@ -684,17 +686,16 @@ static void pci_4u_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in
 	spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
-/* Make physical memory consistent for a single
- * streaming mode DMA translation after a transfer.
- */
-static void pci_4u_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction)
+static void dma_4u_sync_single_for_cpu(struct device *dev,
+				       dma_addr_t bus_addr, size_t sz,
+				       enum dma_data_direction direction)
 {
 	struct iommu *iommu;
 	struct strbuf *strbuf;
 	unsigned long flags, ctx, npages;
 
-	iommu = pdev->dev.archdata.iommu;
-	strbuf = pdev->dev.archdata.stc;
+	iommu = dev->archdata.iommu;
+	strbuf = dev->archdata.stc;
 
 	if (!strbuf->strbuf_enabled)
 		return;
@@ -717,23 +718,22 @@ static void pci_4u_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_
 	}
 
 	/* Step 2: Kick data out of streaming buffers. */
-	pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
+	strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
 
 	spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
-/* Make physical memory consistent for a set of streaming
- * mode DMA translations after a transfer.
- */
-static void pci_4u_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
+static void dma_4u_sync_sg_for_cpu(struct device *dev,
+				   struct scatterlist *sglist, int nelems,
+				   enum dma_data_direction direction)
 {
 	struct iommu *iommu;
 	struct strbuf *strbuf;
 	unsigned long flags, ctx, npages, i;
 	u32 bus_addr;
 
-	iommu = pdev->dev.archdata.iommu;
-	strbuf = pdev->dev.archdata.stc;
+	iommu = dev->archdata.iommu;
+	strbuf = dev->archdata.stc;
 
 	if (!strbuf->strbuf_enabled)
 		return;
@@ -759,65 +759,51 @@ static void pci_4u_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist
 	i--;
 	npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length)
 		  - bus_addr) >> IO_PAGE_SHIFT;
-	pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
+	strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
 
 	spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
-const struct pci_iommu_ops pci_sun4u_iommu_ops = {
-	.alloc_consistent		= pci_4u_alloc_consistent,
-	.free_consistent		= pci_4u_free_consistent,
-	.map_single			= pci_4u_map_single,
-	.unmap_single			= pci_4u_unmap_single,
-	.map_sg				= pci_4u_map_sg,
-	.unmap_sg			= pci_4u_unmap_sg,
-	.dma_sync_single_for_cpu	= pci_4u_dma_sync_single_for_cpu,
-	.dma_sync_sg_for_cpu		= pci_4u_dma_sync_sg_for_cpu,
+const struct dma_ops sun4u_dma_ops = {
+	.alloc_coherent		= dma_4u_alloc_coherent,
+	.free_coherent		= dma_4u_free_coherent,
+	.map_single		= dma_4u_map_single,
+	.unmap_single		= dma_4u_unmap_single,
+	.map_sg			= dma_4u_map_sg,
+	.unmap_sg		= dma_4u_unmap_sg,
+	.sync_single_for_cpu	= dma_4u_sync_single_for_cpu,
+	.sync_sg_for_cpu	= dma_4u_sync_sg_for_cpu,
 };
 
-static void ali_sound_dma_hack(struct pci_dev *pdev, int set_bit)
-{
-	struct pci_dev *ali_isa_bridge;
-	u8 val;
+const struct dma_ops *dma_ops = &sun4u_dma_ops;
+EXPORT_SYMBOL(dma_ops);
 
-	/* ALI sound chips generate 31-bits of DMA, a special register
-	 * determines what bit 31 is emitted as.
-	 */
-	ali_isa_bridge = pci_get_device(PCI_VENDOR_ID_AL,
-					 PCI_DEVICE_ID_AL_M1533,
-					 NULL);
-
-	pci_read_config_byte(ali_isa_bridge, 0x7e, &val);
-	if (set_bit)
-		val |= 0x01;
-	else
-		val &= ~0x01;
-	pci_write_config_byte(ali_isa_bridge, 0x7e, val);
-	pci_dev_put(ali_isa_bridge);
-}
-
-int pci_dma_supported(struct pci_dev *pdev, u64 device_mask)
+int dma_supported(struct device *dev, u64 device_mask)
 {
-	u64 dma_addr_mask;
+	struct iommu *iommu = dev->archdata.iommu;
+	u64 dma_addr_mask = iommu->dma_addr_mask;
 
-	if (pdev == NULL) {
-		dma_addr_mask = 0xffffffff;
-	} else {
-		struct iommu *iommu = pdev->dev.archdata.iommu;
+	if (device_mask >= (1UL << 32UL))
+		return 0;
 
-		dma_addr_mask = iommu->dma_addr_mask;
+	if ((device_mask & dma_addr_mask) == dma_addr_mask)
+		return 1;
 
-		if (pdev->vendor == PCI_VENDOR_ID_AL &&
-		    pdev->device == PCI_DEVICE_ID_AL_M5451 &&
-		    device_mask == 0x7fffffff) {
-			ali_sound_dma_hack(pdev,
-					   (dma_addr_mask & 0x80000000) != 0);
-			return 1;
-		}
-	}
+#ifdef CONFIG_PCI
+	if (dev->bus == &pci_bus_type)
+		return pci_dma_supported(to_pci_dev(dev), device_mask);
+#endif
 
-	if (device_mask >= (1UL << 32UL))
-		return 0;
+	return 0;
+}
+EXPORT_SYMBOL(dma_supported);
 
-	return (device_mask & dma_addr_mask) == dma_addr_mask;
+int dma_set_mask(struct device *dev, u64 dma_mask)
+{
+#ifdef CONFIG_PCI
+	if (dev->bus == &pci_bus_type)
+		return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
+#endif
+	return -EINVAL;
 }
+EXPORT_SYMBOL(dma_set_mask);

+ 2 - 0
arch/sparc64/kernel/isa.c

@@ -90,6 +90,8 @@ static void __init isa_fill_devices(struct sparc_isa_bridge *isa_br)
 		sd = &isa_dev->ofdev.dev.archdata;
 		sd->prom_node = dp;
 		sd->op = &isa_dev->ofdev;
+		sd->iommu = isa_br->ofdev.dev.parent->archdata.iommu;
+		sd->stc = isa_br->ofdev.dev.parent->archdata.stc;
 
 		isa_dev->ofdev.node = dp;
 		isa_dev->ofdev.dev.parent = &isa_br->ofdev.dev;

+ 61 - 16
arch/sparc64/kernel/pci.c

@@ -283,12 +283,6 @@ int __init pcic_present(void)
 	return pci_controller_scan(pci_is_controller);
 }
 
-const struct pci_iommu_ops *pci_iommu_ops;
-EXPORT_SYMBOL(pci_iommu_ops);
-
-extern const struct pci_iommu_ops pci_sun4u_iommu_ops,
-	pci_sun4v_iommu_ops;
-
 /* Find each controller in the system, attach and initialize
  * software state structure for each and link into the
  * pci_pbm_root.  Setup the controller enough such
@@ -296,11 +290,6 @@ extern const struct pci_iommu_ops pci_sun4u_iommu_ops,
  */
 static void __init pci_controller_probe(void)
 {
-	if (tlb_type == hypervisor)
-		pci_iommu_ops = &pci_sun4v_iommu_ops;
-	else
-		pci_iommu_ops = &pci_sun4u_iommu_ops;
-
 	printk("PCI: Probing for controllers.\n");
 
 	pci_controller_scan(pci_controller_init);
@@ -406,6 +395,10 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
 	sd->op = of_find_device_by_node(node);
 	sd->msi_num = 0xffffffff;
 
+	sd = &sd->op->dev.archdata;
+	sd->iommu = pbm->iommu;
+	sd->stc = &pbm->stc;
+
 	type = of_get_property(node, "device_type", NULL);
 	if (type == NULL)
 		type = "";
@@ -422,10 +415,15 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
 	dev->multifunction = 0;		/* maybe a lie? */
 
 	if (host_controller) {
-		dev->vendor = 0x108e;
-		dev->device = 0x8000;
-		dev->subsystem_vendor = 0x0000;
-		dev->subsystem_device = 0x0000;
+		if (tlb_type != hypervisor) {
+			pci_read_config_word(dev, PCI_VENDOR_ID,
+					     &dev->vendor);
+			pci_read_config_word(dev, PCI_DEVICE_ID,
+					     &dev->device);
+		} else {
+			dev->vendor = PCI_VENDOR_ID_SUN;
+			dev->device = 0x80f0;
+		}
 		dev->cfg_size = 256;
 		dev->class = PCI_CLASS_BRIDGE_HOST << 8;
 		sprintf(pci_name(dev), "%04x:%02x:%02x.%d", pci_domain_nr(bus),
@@ -818,7 +816,7 @@ int pci_host_bridge_read_pci_cfg(struct pci_bus *bus_dev,
 {
 	static u8 fake_pci_config[] = {
 		0x8e, 0x10, /* Vendor: 0x108e (Sun) */
-		0x00, 0x80, /* Device: 0x8000 (PBM) */
+		0xf0, 0x80, /* Device: 0x80f0 (Fire) */
 		0x46, 0x01, /* Command: 0x0146 (SERR, PARITY, MASTER, MEM) */
 		0xa0, 0x22, /* Status: 0x02a0 (DEVSEL_MED, FB2B, 66MHZ) */
 		0x00, 0x00, 0x00, 0x06, /* Class: 0x06000000 host bridge */
@@ -1221,4 +1219,51 @@ struct device_node *pci_device_to_OF_node(struct pci_dev *pdev)
 }
 EXPORT_SYMBOL(pci_device_to_OF_node);
 
+static void ali_sound_dma_hack(struct pci_dev *pdev, int set_bit)
+{
+	struct pci_dev *ali_isa_bridge;
+	u8 val;
+
+	/* ALI sound chips generate 31-bits of DMA, a special register
+	 * determines what bit 31 is emitted as.
+	 */
+	ali_isa_bridge = pci_get_device(PCI_VENDOR_ID_AL,
+					 PCI_DEVICE_ID_AL_M1533,
+					 NULL);
+
+	pci_read_config_byte(ali_isa_bridge, 0x7e, &val);
+	if (set_bit)
+		val |= 0x01;
+	else
+		val &= ~0x01;
+	pci_write_config_byte(ali_isa_bridge, 0x7e, val);
+	pci_dev_put(ali_isa_bridge);
+}
+
+int pci_dma_supported(struct pci_dev *pdev, u64 device_mask)
+{
+	u64 dma_addr_mask;
+
+	if (pdev == NULL) {
+		dma_addr_mask = 0xffffffff;
+	} else {
+		struct iommu *iommu = pdev->dev.archdata.iommu;
+
+		dma_addr_mask = iommu->dma_addr_mask;
+
+		if (pdev->vendor == PCI_VENDOR_ID_AL &&
+		    pdev->device == PCI_DEVICE_ID_AL_M5451 &&
+		    device_mask == 0x7fffffff) {
+			ali_sound_dma_hack(pdev,
+					   (dma_addr_mask & 0x80000000) != 0);
+			return 1;
+		}
+	}
+
+	if (device_mask >= (1UL << 32UL))
+		return 0;
+
+	return (device_mask & dma_addr_mask) == dma_addr_mask;
+}
+
 #endif /* !(CONFIG_PCI) */

+ 116 - 7
arch/sparc64/kernel/pci_common.c

@@ -44,6 +44,67 @@ static void *sun4u_config_mkaddr(struct pci_pbm_info *pbm,
 	return (void *)	(pbm->config_space | bus | devfn | reg);
 }
 
+/* At least on Sabre, it is necessary to access all PCI host controller
+ * registers at their natural size, otherwise zeros are returned.
+ * Strange but true, and I see no language in the UltraSPARC-IIi
+ * programmer's manual that mentions this even indirectly.
+ */
+static int sun4u_read_pci_cfg_host(struct pci_pbm_info *pbm,
+				   unsigned char bus, unsigned int devfn,
+				   int where, int size, u32 *value)
+{
+	u32 tmp32, *addr;
+	u16 tmp16;
+	u8 tmp8;
+
+	addr = sun4u_config_mkaddr(pbm, bus, devfn, where);
+	if (!addr)
+		return PCIBIOS_SUCCESSFUL;
+
+	switch (size) {
+	case 1:
+		if (where < 8) {
+			unsigned long align = (unsigned long) addr;
+
+			align &= ~1;
+			pci_config_read16((u16 *)align, &tmp16);
+			if (where & 1)
+				*value = tmp16 >> 8;
+			else
+				*value = tmp16 & 0xff;
+		} else {
+			pci_config_read8((u8 *)addr, &tmp8);
+			*value = (u32) tmp8;
+		}
+		break;
+
+	case 2:
+		if (where < 8) {
+			pci_config_read16((u16 *)addr, &tmp16);
+			*value = (u32) tmp16;
+		} else {
+			pci_config_read8((u8 *)addr, &tmp8);
+			*value = (u32) tmp8;
+			pci_config_read8(((u8 *)addr) + 1, &tmp8);
+			*value |= ((u32) tmp8) << 8;
+		}
+		break;
+
+	case 4:
+		tmp32 = 0xffffffff;
+		sun4u_read_pci_cfg_host(pbm, bus, devfn,
+					where, 2, &tmp32);
+		*value = tmp32;
+
+		tmp32 = 0xffffffff;
+		sun4u_read_pci_cfg_host(pbm, bus, devfn,
+					where + 2, 2, &tmp32);
+		*value |= tmp32 << 16;
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
 static int sun4u_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
 			      int where, int size, u32 *value)
 {
@@ -53,10 +114,6 @@ static int sun4u_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
 	u16 tmp16;
 	u8 tmp8;
 
-	if (bus_dev == pbm->pci_bus && devfn == 0x00)
-		return pci_host_bridge_read_pci_cfg(bus_dev, devfn, where,
-						    size, value);
-
 	switch (size) {
 	case 1:
 		*value = 0xff;
@@ -69,6 +126,10 @@ static int sun4u_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
 		break;
 	}
 
+	if (!bus_dev->number && !PCI_SLOT(devfn))
+		return sun4u_read_pci_cfg_host(pbm, bus, devfn, where,
+					       size, value);
+
 	addr = sun4u_config_mkaddr(pbm, bus, devfn, where);
 	if (!addr)
 		return PCIBIOS_SUCCESSFUL;
@@ -101,6 +162,53 @@ static int sun4u_read_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
 	return PCIBIOS_SUCCESSFUL;
 }
 
+static int sun4u_write_pci_cfg_host(struct pci_pbm_info *pbm,
+				    unsigned char bus, unsigned int devfn,
+				    int where, int size, u32 value)
+{
+	u32 *addr;
+
+	addr = sun4u_config_mkaddr(pbm, bus, devfn, where);
+	if (!addr)
+		return PCIBIOS_SUCCESSFUL;
+
+	switch (size) {
+	case 1:
+		if (where < 8) {
+			unsigned long align = (unsigned long) addr;
+			u16 tmp16;
+
+			align &= ~1;
+			pci_config_read16((u16 *)align, &tmp16);
+			if (where & 1) {
+				tmp16 &= 0x00ff;
+				tmp16 |= value << 8;
+			} else {
+				tmp16 &= 0xff00;
+				tmp16 |= value;
+			}
+			pci_config_write16((u16 *)align, tmp16);
+		} else
+			pci_config_write8((u8 *)addr, value);
+		break;
+	case 2:
+		if (where < 8) {
+			pci_config_write16((u16 *)addr, value);
+		} else {
+			pci_config_write8((u8 *)addr, value & 0xff);
+			pci_config_write8(((u8 *)addr) + 1, value >> 8);
+		}
+		break;
+	case 4:
+		sun4u_write_pci_cfg_host(pbm, bus, devfn,
+					 where, 2, value & 0xffff);
+		sun4u_write_pci_cfg_host(pbm, bus, devfn,
+					 where + 2, 2, value >> 16);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
 static int sun4u_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
 			       int where, int size, u32 value)
 {
@@ -108,9 +216,10 @@ static int sun4u_write_pci_cfg(struct pci_bus *bus_dev, unsigned int devfn,
 	unsigned char bus = bus_dev->number;
 	u32 *addr;
 
-	if (bus_dev == pbm->pci_bus && devfn == 0x00)
-		return pci_host_bridge_write_pci_cfg(bus_dev, devfn, where,
-						     size, value);
+	if (!bus_dev->number && !PCI_SLOT(devfn))
+		return sun4u_write_pci_cfg_host(pbm, bus, devfn, where,
+						size, value);
+
 	addr = sun4u_config_mkaddr(pbm, bus, devfn, where);
 	if (!addr)
 		return PCIBIOS_SUCCESSFUL;

+ 16 - 8
arch/sparc64/kernel/pci_fire.c

@@ -39,12 +39,12 @@ static void pci_fire_scan_bus(struct pci_pbm_info *pbm)
 #define FIRE_IOMMU_FLUSH	0x40100UL
 #define FIRE_IOMMU_FLUSHINV	0x40108UL
 
-static void pci_fire_pbm_iommu_init(struct pci_pbm_info *pbm)
+static int pci_fire_pbm_iommu_init(struct pci_pbm_info *pbm)
 {
 	struct iommu *iommu = pbm->iommu;
 	u32 vdma[2], dma_mask;
 	u64 control;
-	int tsbsize;
+	int tsbsize, err;
 
 	/* No virtual-dma property on these guys, use largest size.  */
 	vdma[0] = 0xc0000000; /* base */
@@ -68,7 +68,9 @@ static void pci_fire_pbm_iommu_init(struct pci_pbm_info *pbm)
 	 */
 	fire_write(iommu->iommu_flushinv, ~(u64)0);
 
-	pci_iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask);
+	err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask);
+	if (err)
+		return err;
 
 	fire_write(iommu->iommu_tsbbase, __pa(iommu->page_table) | 0x7UL);
 
@@ -78,6 +80,8 @@ static void pci_fire_pbm_iommu_init(struct pci_pbm_info *pbm)
 		    0x00000002 /* Bypass enable */		|
 		    0x00000001 /* Translation enable */);
 	fire_write(iommu->iommu_control, control);
+
+	return 0;
 }
 
 /* Based at pbm->controller_regs */
@@ -167,8 +171,8 @@ static void pci_fire_hw_init(struct pci_pbm_info *pbm)
 	fire_write(pbm->pbm_regs + FIRE_PEC_IENAB, ~(u64)0);
 }
 
-static void pci_fire_pbm_init(struct pci_controller_info *p,
-			      struct device_node *dp, u32 portid)
+static int pci_fire_pbm_init(struct pci_controller_info *p,
+			     struct device_node *dp, u32 portid)
 {
 	const struct linux_prom64_registers *regs;
 	struct pci_pbm_info *pbm;
@@ -203,7 +207,8 @@ static void pci_fire_pbm_init(struct pci_controller_info *p,
 	pci_get_pbm_props(pbm);
 
 	pci_fire_hw_init(pbm);
-	pci_fire_pbm_iommu_init(pbm);
+
+	return pci_fire_pbm_iommu_init(pbm);
 }
 
 static inline int portid_compare(u32 x, u32 y)
@@ -222,7 +227,8 @@ void fire_pci_init(struct device_node *dp, const char *model_name)
 
 	for (pbm = pci_pbm_root; pbm; pbm = pbm->next) {
 		if (portid_compare(pbm->portid, portid)) {
-			pci_fire_pbm_init(pbm->parent, dp, portid);
+			if (pci_fire_pbm_init(pbm->parent, dp, portid))
+				goto fatal_memory_error;
 			return;
 		}
 	}
@@ -250,7 +256,9 @@ void fire_pci_init(struct device_node *dp, const char *model_name)
 	 */
 	pci_memspace_mask = 0x7fffffffUL;
 
-	pci_fire_pbm_init(p, dp, portid);
+	if (pci_fire_pbm_init(p, dp, portid))
+		goto fatal_memory_error;
+
 	return;
 
 fatal_memory_error:

+ 21 - 11
arch/sparc64/kernel/pci_psycho.c

@@ -813,16 +813,19 @@ static void psycho_scan_bus(struct pci_pbm_info *pbm)
 	psycho_register_error_handlers(pbm);
 }
 
-static void psycho_iommu_init(struct pci_pbm_info *pbm)
+static int psycho_iommu_init(struct pci_pbm_info *pbm)
 {
 	struct iommu *iommu = pbm->iommu;
 	unsigned long i;
 	u64 control;
+	int err;
 
 	/* Register addresses. */
 	iommu->iommu_control  = pbm->controller_regs + PSYCHO_IOMMU_CONTROL;
 	iommu->iommu_tsbbase  = pbm->controller_regs + PSYCHO_IOMMU_TSBBASE;
 	iommu->iommu_flush    = pbm->controller_regs + PSYCHO_IOMMU_FLUSH;
+	iommu->iommu_tags     = iommu->iommu_flush + (0xa580UL - 0x0210UL);
+
 	/* PSYCHO's IOMMU lacks ctx flushing. */
 	iommu->iommu_ctxflush = 0;
 
@@ -845,7 +848,9 @@ static void psycho_iommu_init(struct pci_pbm_info *pbm)
 	/* Leave diag mode enabled for full-flushing done
 	 * in pci_iommu.c
 	 */
-	pci_iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff);
+	err = iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff);
+	if (err)
+		return err;
 
 	psycho_write(pbm->controller_regs + PSYCHO_IOMMU_TSBBASE,
 		     __pa(iommu->page_table));
@@ -858,6 +863,8 @@ static void psycho_iommu_init(struct pci_pbm_info *pbm)
 	/* If necessary, hook us up for starfire IRQ translations. */
 	if (this_is_starfire)
 		starfire_hookup(pbm->portid);
+
+	return 0;
 }
 
 #define PSYCHO_IRQ_RETRY	0x1a00UL
@@ -1031,15 +1038,12 @@ void psycho_init(struct device_node *dp, char *model_name)
 	}
 
 	p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
-	if (!p) {
-		prom_printf("PSYCHO: Fatal memory allocation error.\n");
-		prom_halt();
-	}
+	if (!p)
+		goto fatal_memory_error;
 	iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC);
-	if (!iommu) {
-		prom_printf("PSYCHO: Fatal memory allocation error.\n");
-		prom_halt();
-	}
+	if (!iommu)
+		goto fatal_memory_error;
+
 	p->pbm_A.iommu = p->pbm_B.iommu = iommu;
 
 	p->pbm_A.portid = upa_portid;
@@ -1062,8 +1066,14 @@ void psycho_init(struct device_node *dp, char *model_name)
 
 	psycho_controller_hwinit(&p->pbm_A);
 
-	psycho_iommu_init(&p->pbm_A);
+	if (psycho_iommu_init(&p->pbm_A))
+		goto fatal_memory_error;
 
 	is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000);
 	psycho_pbm_init(p, dp, is_pbm_a);
+	return;
+
+fatal_memory_error:
+	prom_printf("PSYCHO: Fatal memory allocation error.\n");
+	prom_halt();
 }

+ 22 - 13
arch/sparc64/kernel/pci_sabre.c

@@ -672,18 +672,20 @@ static void sabre_scan_bus(struct pci_pbm_info *pbm)
 	sabre_register_error_handlers(pbm);
 }
 
-static void sabre_iommu_init(struct pci_pbm_info *pbm,
-			     int tsbsize, unsigned long dvma_offset,
-			     u32 dma_mask)
+static int sabre_iommu_init(struct pci_pbm_info *pbm,
+			    int tsbsize, unsigned long dvma_offset,
+			    u32 dma_mask)
 {
 	struct iommu *iommu = pbm->iommu;
 	unsigned long i;
 	u64 control;
+	int err;
 
 	/* Register addresses. */
 	iommu->iommu_control  = pbm->controller_regs + SABRE_IOMMU_CONTROL;
 	iommu->iommu_tsbbase  = pbm->controller_regs + SABRE_IOMMU_TSBBASE;
 	iommu->iommu_flush    = pbm->controller_regs + SABRE_IOMMU_FLUSH;
+	iommu->iommu_tags     = iommu->iommu_flush + (0xa580UL - 0x0210UL);
 	iommu->write_complete_reg = pbm->controller_regs + SABRE_WRSYNC;
 	/* Sabre's IOMMU lacks ctx flushing. */
 	iommu->iommu_ctxflush = 0;
@@ -701,7 +703,10 @@ static void sabre_iommu_init(struct pci_pbm_info *pbm,
 	/* Leave diag mode enabled for full-flushing done
 	 * in pci_iommu.c
 	 */
-	pci_iommu_table_init(iommu, tsbsize * 1024 * 8, dvma_offset, dma_mask);
+	err = iommu_table_init(iommu, tsbsize * 1024 * 8,
+			       dvma_offset, dma_mask);
+	if (err)
+		return err;
 
 	sabre_write(pbm->controller_regs + SABRE_IOMMU_TSBBASE,
 		    __pa(iommu->page_table));
@@ -722,6 +727,8 @@ static void sabre_iommu_init(struct pci_pbm_info *pbm,
 		break;
 	}
 	sabre_write(pbm->controller_regs + SABRE_IOMMU_CONTROL, control);
+
+	return 0;
 }
 
 static void sabre_pbm_init(struct pci_controller_info *p, struct pci_pbm_info *pbm, struct device_node *dp)
@@ -775,16 +782,12 @@ void sabre_init(struct device_node *dp, char *model_name)
 	}
 
 	p = kzalloc(sizeof(*p), GFP_ATOMIC);
-	if (!p) {
-		prom_printf("SABRE: Error, kmalloc(pci_controller_info) failed.\n");
-		prom_halt();
-	}
+	if (!p)
+		goto fatal_memory_error;
 
 	iommu = kzalloc(sizeof(*iommu), GFP_ATOMIC);
-	if (!iommu) {
-		prom_printf("SABRE: Error, kmalloc(pci_iommu) failed.\n");
-		prom_halt();
-	}
+	if (!iommu)
+		goto fatal_memory_error;
 	pbm = &p->pbm_A;
 	pbm->iommu = iommu;
 
@@ -847,10 +850,16 @@ void sabre_init(struct device_node *dp, char *model_name)
 			prom_halt();
 	}
 
-	sabre_iommu_init(pbm, tsbsize, vdma[0], dma_mask);
+	if (sabre_iommu_init(pbm, tsbsize, vdma[0], dma_mask))
+		goto fatal_memory_error;
 
 	/*
 	 * Look for APB underneath.
 	 */
 	sabre_pbm_init(p, pbm, dp);
+	return;
+
+fatal_memory_error:
+	prom_printf("SABRE: Fatal memory allocation error.\n");
+	prom_halt();
 }

+ 28 - 14
arch/sparc64/kernel/pci_schizo.c

@@ -1148,14 +1148,14 @@ static void schizo_pbm_strbuf_init(struct pci_pbm_info *pbm)
 #define SCHIZO_IOMMU_FLUSH		(0x00210UL)
 #define SCHIZO_IOMMU_CTXFLUSH		(0x00218UL)
 
-static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
+static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
 {
 	struct iommu *iommu = pbm->iommu;
 	unsigned long i, tagbase, database;
 	struct property *prop;
 	u32 vdma[2], dma_mask;
+	int tsbsize, err;
 	u64 control;
-	int tsbsize;
 
 	prop = of_find_property(pbm->prom_node, "virtual-dma", NULL);
 	if (prop) {
@@ -1195,6 +1195,7 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
 	iommu->iommu_control  = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL;
 	iommu->iommu_tsbbase  = pbm->pbm_regs + SCHIZO_IOMMU_TSBBASE;
 	iommu->iommu_flush    = pbm->pbm_regs + SCHIZO_IOMMU_FLUSH;
+	iommu->iommu_tags     = iommu->iommu_flush + (0xa580UL - 0x0210UL);
 	iommu->iommu_ctxflush = pbm->pbm_regs + SCHIZO_IOMMU_CTXFLUSH;
 
 	/* We use the main control/status register of SCHIZO as the write
@@ -1219,7 +1220,9 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
 	/* Leave diag mode enabled for full-flushing done
 	 * in pci_iommu.c
 	 */
-	pci_iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask);
+	err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask);
+	if (err)
+		return err;
 
 	schizo_write(iommu->iommu_tsbbase, __pa(iommu->page_table));
 
@@ -1236,6 +1239,8 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
 
 	control |= SCHIZO_IOMMU_CTRL_ENAB;
 	schizo_write(iommu->iommu_control, control);
+
+	return 0;
 }
 
 #define SCHIZO_PCI_IRQ_RETRY	(0x1a00UL)
@@ -1328,14 +1333,14 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm)
 	}
 }
 
-static void schizo_pbm_init(struct pci_controller_info *p,
-			    struct device_node *dp, u32 portid,
-			    int chip_type)
+static int schizo_pbm_init(struct pci_controller_info *p,
+			   struct device_node *dp, u32 portid,
+			   int chip_type)
 {
 	const struct linux_prom64_registers *regs;
 	struct pci_pbm_info *pbm;
 	const char *chipset_name;
-	int is_pbm_a;
+	int is_pbm_a, err;
 
 	switch (chip_type) {
 	case PBM_CHIP_TYPE_TOMATILLO:
@@ -1406,8 +1411,13 @@ static void schizo_pbm_init(struct pci_controller_info *p,
 
 	pci_get_pbm_props(pbm);
 
-	schizo_pbm_iommu_init(pbm);
+	err = schizo_pbm_iommu_init(pbm);
+	if (err)
+		return err;
+
 	schizo_pbm_strbuf_init(pbm);
+
+	return 0;
 }
 
 static inline int portid_compare(u32 x, u32 y, int chip_type)
@@ -1431,34 +1441,38 @@ static void __schizo_init(struct device_node *dp, char *model_name, int chip_typ
 
 	for (pbm = pci_pbm_root; pbm; pbm = pbm->next) {
 		if (portid_compare(pbm->portid, portid, chip_type)) {
-			schizo_pbm_init(pbm->parent, dp, portid, chip_type);
+			if (schizo_pbm_init(pbm->parent, dp,
+					    portid, chip_type))
+				goto fatal_memory_error;
 			return;
 		}
 	}
 
 	p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);
 	if (!p)
-		goto memfail;
+		goto fatal_memory_error;
 
 	iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC);
 	if (!iommu)
-		goto memfail;
+		goto fatal_memory_error;
 
 	p->pbm_A.iommu = iommu;
 
 	iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC);
 	if (!iommu)
-		goto memfail;
+		goto fatal_memory_error;
 
 	p->pbm_B.iommu = iommu;
 
 	/* Like PSYCHO we have a 2GB aligned area for memory space. */
 	pci_memspace_mask = 0x7fffffffUL;
 
-	schizo_pbm_init(p, dp, portid, chip_type);
+	if (schizo_pbm_init(p, dp, portid, chip_type))
+		goto fatal_memory_error;
+
 	return;
 
-memfail:
+fatal_memory_error:
 	prom_printf("SCHIZO: Fatal memory allocation error.\n");
 	prom_halt();
 }

+ 91 - 77
arch/sparc64/kernel/pci_sun4v.c

@@ -33,30 +33,30 @@ static unsigned long vpci_minor = 1;
 #define PGLIST_NENTS	(PAGE_SIZE / sizeof(u64))
 
 struct iommu_batch {
-	struct pci_dev	*pdev;		/* Device mapping is for.	*/
+	struct device	*dev;		/* Device mapping is for.	*/
 	unsigned long	prot;		/* IOMMU page protections	*/
 	unsigned long	entry;		/* Index into IOTSB.		*/
 	u64		*pglist;	/* List of physical pages	*/
 	unsigned long	npages;		/* Number of pages in list.	*/
 };
 
-static DEFINE_PER_CPU(struct iommu_batch, pci_iommu_batch);
+static DEFINE_PER_CPU(struct iommu_batch, iommu_batch);
 
 /* Interrupts must be disabled.  */
-static inline void pci_iommu_batch_start(struct pci_dev *pdev, unsigned long prot, unsigned long entry)
+static inline void iommu_batch_start(struct device *dev, unsigned long prot, unsigned long entry)
 {
-	struct iommu_batch *p = &__get_cpu_var(pci_iommu_batch);
+	struct iommu_batch *p = &__get_cpu_var(iommu_batch);
 
-	p->pdev		= pdev;
+	p->dev		= dev;
 	p->prot		= prot;
 	p->entry	= entry;
 	p->npages	= 0;
 }
 
 /* Interrupts must be disabled.  */
-static long pci_iommu_batch_flush(struct iommu_batch *p)
+static long iommu_batch_flush(struct iommu_batch *p)
 {
-	struct pci_pbm_info *pbm = p->pdev->dev.archdata.host_controller;
+	struct pci_pbm_info *pbm = p->dev->archdata.host_controller;
 	unsigned long devhandle = pbm->devhandle;
 	unsigned long prot = p->prot;
 	unsigned long entry = p->entry;
@@ -70,7 +70,7 @@ static long pci_iommu_batch_flush(struct iommu_batch *p)
 					  npages, prot, __pa(pglist));
 		if (unlikely(num < 0)) {
 			if (printk_ratelimit())
-				printk("pci_iommu_batch_flush: IOMMU map of "
+				printk("iommu_batch_flush: IOMMU map of "
 				       "[%08lx:%08lx:%lx:%lx:%lx] failed with "
 				       "status %ld\n",
 				       devhandle, HV_PCI_TSBID(0, entry),
@@ -90,30 +90,30 @@ static long pci_iommu_batch_flush(struct iommu_batch *p)
 }
 
 /* Interrupts must be disabled.  */
-static inline long pci_iommu_batch_add(u64 phys_page)
+static inline long iommu_batch_add(u64 phys_page)
 {
-	struct iommu_batch *p = &__get_cpu_var(pci_iommu_batch);
+	struct iommu_batch *p = &__get_cpu_var(iommu_batch);
 
 	BUG_ON(p->npages >= PGLIST_NENTS);
 
 	p->pglist[p->npages++] = phys_page;
 	if (p->npages == PGLIST_NENTS)
-		return pci_iommu_batch_flush(p);
+		return iommu_batch_flush(p);
 
 	return 0;
 }
 
 /* Interrupts must be disabled.  */
-static inline long pci_iommu_batch_end(void)
+static inline long iommu_batch_end(void)
 {
-	struct iommu_batch *p = &__get_cpu_var(pci_iommu_batch);
+	struct iommu_batch *p = &__get_cpu_var(iommu_batch);
 
 	BUG_ON(p->npages >= PGLIST_NENTS);
 
-	return pci_iommu_batch_flush(p);
+	return iommu_batch_flush(p);
 }
 
-static long pci_arena_alloc(struct iommu_arena *arena, unsigned long npages)
+static long arena_alloc(struct iommu_arena *arena, unsigned long npages)
 {
 	unsigned long n, i, start, end, limit;
 	int pass;
@@ -152,7 +152,8 @@ again:
 	return n;
 }
 
-static void pci_arena_free(struct iommu_arena *arena, unsigned long base, unsigned long npages)
+static void arena_free(struct iommu_arena *arena, unsigned long base,
+		       unsigned long npages)
 {
 	unsigned long i;
 
@@ -160,7 +161,8 @@ static void pci_arena_free(struct iommu_arena *arena, unsigned long base, unsign
 		__clear_bit(i, arena->map);
 }
 
-static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp, gfp_t gfp)
+static void *dma_4v_alloc_coherent(struct device *dev, size_t size,
+				   dma_addr_t *dma_addrp, gfp_t gfp)
 {
 	struct iommu *iommu;
 	unsigned long flags, order, first_page, npages, n;
@@ -180,10 +182,10 @@ static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
 
 	memset((char *)first_page, 0, PAGE_SIZE << order);
 
-	iommu = pdev->dev.archdata.iommu;
+	iommu = dev->archdata.iommu;
 
 	spin_lock_irqsave(&iommu->lock, flags);
-	entry = pci_arena_alloc(&iommu->arena, npages);
+	entry = arena_alloc(&iommu->arena, npages);
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
 	if (unlikely(entry < 0L))
@@ -196,18 +198,18 @@ static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
 
 	local_irq_save(flags);
 
-	pci_iommu_batch_start(pdev,
-			      (HV_PCI_MAP_ATTR_READ |
-			       HV_PCI_MAP_ATTR_WRITE),
-			      entry);
+	iommu_batch_start(dev,
+			  (HV_PCI_MAP_ATTR_READ |
+			   HV_PCI_MAP_ATTR_WRITE),
+			  entry);
 
 	for (n = 0; n < npages; n++) {
-		long err = pci_iommu_batch_add(first_page + (n * PAGE_SIZE));
+		long err = iommu_batch_add(first_page + (n * PAGE_SIZE));
 		if (unlikely(err < 0L))
 			goto iommu_map_fail;
 	}
 
-	if (unlikely(pci_iommu_batch_end() < 0L))
+	if (unlikely(iommu_batch_end() < 0L))
 		goto iommu_map_fail;
 
 	local_irq_restore(flags);
@@ -217,7 +219,7 @@ static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr
 iommu_map_fail:
 	/* Interrupts are disabled.  */
 	spin_lock(&iommu->lock);
-	pci_arena_free(&iommu->arena, entry, npages);
+	arena_free(&iommu->arena, entry, npages);
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
 arena_alloc_fail:
@@ -225,7 +227,8 @@ arena_alloc_fail:
 	return NULL;
 }
 
-static void pci_4v_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_t dvma)
+static void dma_4v_free_coherent(struct device *dev, size_t size, void *cpu,
+				 dma_addr_t dvma)
 {
 	struct pci_pbm_info *pbm;
 	struct iommu *iommu;
@@ -233,14 +236,14 @@ static void pci_4v_free_consistent(struct pci_dev *pdev, size_t size, void *cpu,
 	u32 devhandle;
 
 	npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT;
-	iommu = pdev->dev.archdata.iommu;
-	pbm = pdev->dev.archdata.host_controller;
+	iommu = dev->archdata.iommu;
+	pbm = dev->archdata.host_controller;
 	devhandle = pbm->devhandle;
 	entry = ((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
 
 	spin_lock_irqsave(&iommu->lock, flags);
 
-	pci_arena_free(&iommu->arena, entry, npages);
+	arena_free(&iommu->arena, entry, npages);
 
 	do {
 		unsigned long num;
@@ -258,7 +261,8 @@ static void pci_4v_free_consistent(struct pci_dev *pdev, size_t size, void *cpu,
 		free_pages((unsigned long)cpu, order);
 }
 
-static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direction)
+static dma_addr_t dma_4v_map_single(struct device *dev, void *ptr, size_t sz,
+				    enum dma_data_direction direction)
 {
 	struct iommu *iommu;
 	unsigned long flags, npages, oaddr;
@@ -267,9 +271,9 @@ static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz,
 	unsigned long prot;
 	long entry;
 
-	iommu = pdev->dev.archdata.iommu;
+	iommu = dev->archdata.iommu;
 
-	if (unlikely(direction == PCI_DMA_NONE))
+	if (unlikely(direction == DMA_NONE))
 		goto bad;
 
 	oaddr = (unsigned long)ptr;
@@ -277,7 +281,7 @@ static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz,
 	npages >>= IO_PAGE_SHIFT;
 
 	spin_lock_irqsave(&iommu->lock, flags);
-	entry = pci_arena_alloc(&iommu->arena, npages);
+	entry = arena_alloc(&iommu->arena, npages);
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
 	if (unlikely(entry < 0L))
@@ -288,19 +292,19 @@ static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz,
 	ret = bus_addr | (oaddr & ~IO_PAGE_MASK);
 	base_paddr = __pa(oaddr & IO_PAGE_MASK);
 	prot = HV_PCI_MAP_ATTR_READ;
-	if (direction != PCI_DMA_TODEVICE)
+	if (direction != DMA_TO_DEVICE)
 		prot |= HV_PCI_MAP_ATTR_WRITE;
 
 	local_irq_save(flags);
 
-	pci_iommu_batch_start(pdev, prot, entry);
+	iommu_batch_start(dev, prot, entry);
 
 	for (i = 0; i < npages; i++, base_paddr += IO_PAGE_SIZE) {
-		long err = pci_iommu_batch_add(base_paddr);
+		long err = iommu_batch_add(base_paddr);
 		if (unlikely(err < 0L))
 			goto iommu_map_fail;
 	}
-	if (unlikely(pci_iommu_batch_end() < 0L))
+	if (unlikely(iommu_batch_end() < 0L))
 		goto iommu_map_fail;
 
 	local_irq_restore(flags);
@@ -310,18 +314,19 @@ static dma_addr_t pci_4v_map_single(struct pci_dev *pdev, void *ptr, size_t sz,
 bad:
 	if (printk_ratelimit())
 		WARN_ON(1);
-	return PCI_DMA_ERROR_CODE;
+	return DMA_ERROR_CODE;
 
 iommu_map_fail:
 	/* Interrupts are disabled.  */
 	spin_lock(&iommu->lock);
-	pci_arena_free(&iommu->arena, entry, npages);
+	arena_free(&iommu->arena, entry, npages);
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
-	return PCI_DMA_ERROR_CODE;
+	return DMA_ERROR_CODE;
 }
 
-static void pci_4v_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction)
+static void dma_4v_unmap_single(struct device *dev, dma_addr_t bus_addr,
+				size_t sz, enum dma_data_direction direction)
 {
 	struct pci_pbm_info *pbm;
 	struct iommu *iommu;
@@ -329,14 +334,14 @@ static void pci_4v_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_
 	long entry;
 	u32 devhandle;
 
-	if (unlikely(direction == PCI_DMA_NONE)) {
+	if (unlikely(direction == DMA_NONE)) {
 		if (printk_ratelimit())
 			WARN_ON(1);
 		return;
 	}
 
-	iommu = pdev->dev.archdata.iommu;
-	pbm = pdev->dev.archdata.host_controller;
+	iommu = dev->archdata.iommu;
+	pbm = dev->archdata.host_controller;
 	devhandle = pbm->devhandle;
 
 	npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK);
@@ -346,7 +351,7 @@ static void pci_4v_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_
 	spin_lock_irqsave(&iommu->lock, flags);
 
 	entry = (bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT;
-	pci_arena_free(&iommu->arena, entry, npages);
+	arena_free(&iommu->arena, entry, npages);
 
 	do {
 		unsigned long num;
@@ -363,7 +368,7 @@ static void pci_4v_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_
 #define SG_ENT_PHYS_ADDRESS(SG)	\
 	(__pa(page_address((SG)->page)) + (SG)->offset)
 
-static inline long fill_sg(long entry, struct pci_dev *pdev,
+static inline long fill_sg(long entry, struct device *dev,
 			   struct scatterlist *sg,
 			   int nused, int nelems, unsigned long prot)
 {
@@ -374,7 +379,7 @@ static inline long fill_sg(long entry, struct pci_dev *pdev,
 
 	local_irq_save(flags);
 
-	pci_iommu_batch_start(pdev, prot, entry);
+	iommu_batch_start(dev, prot, entry);
 
 	for (i = 0; i < nused; i++) {
 		unsigned long pteval = ~0UL;
@@ -415,7 +420,7 @@ static inline long fill_sg(long entry, struct pci_dev *pdev,
 			while (len > 0) {
 				long err;
 
-				err = pci_iommu_batch_add(pteval);
+				err = iommu_batch_add(pteval);
 				if (unlikely(err < 0L))
 					goto iommu_map_failed;
 
@@ -446,7 +451,7 @@ static inline long fill_sg(long entry, struct pci_dev *pdev,
 		dma_sg++;
 	}
 
-	if (unlikely(pci_iommu_batch_end() < 0L))
+	if (unlikely(iommu_batch_end() < 0L))
 		goto iommu_map_failed;
 
 	local_irq_restore(flags);
@@ -457,7 +462,8 @@ iommu_map_failed:
 	return -1L;
 }
 
-static int pci_4v_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
+static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
+			 int nelems, enum dma_data_direction direction)
 {
 	struct iommu *iommu;
 	unsigned long flags, npages, prot;
@@ -469,18 +475,19 @@ static int pci_4v_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n
 	/* Fast path single entry scatterlists. */
 	if (nelems == 1) {
 		sglist->dma_address =
-			pci_4v_map_single(pdev,
-					  (page_address(sglist->page) + sglist->offset),
+			dma_4v_map_single(dev,
+					  (page_address(sglist->page) +
+					   sglist->offset),
 					  sglist->length, direction);
-		if (unlikely(sglist->dma_address == PCI_DMA_ERROR_CODE))
+		if (unlikely(sglist->dma_address == DMA_ERROR_CODE))
 			return 0;
 		sglist->dma_length = sglist->length;
 		return 1;
 	}
 
-	iommu = pdev->dev.archdata.iommu;
+	iommu = dev->archdata.iommu;
 	
-	if (unlikely(direction == PCI_DMA_NONE))
+	if (unlikely(direction == DMA_NONE))
 		goto bad;
 
 	/* Step 1: Prepare scatter list. */
@@ -488,7 +495,7 @@ static int pci_4v_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n
 
 	/* Step 2: Allocate a cluster and context, if necessary. */
 	spin_lock_irqsave(&iommu->lock, flags);
-	entry = pci_arena_alloc(&iommu->arena, npages);
+	entry = arena_alloc(&iommu->arena, npages);
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
 	if (unlikely(entry < 0L))
@@ -510,10 +517,10 @@ static int pci_4v_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int n
 
 	/* Step 4: Create the mappings. */
 	prot = HV_PCI_MAP_ATTR_READ;
-	if (direction != PCI_DMA_TODEVICE)
+	if (direction != DMA_TO_DEVICE)
 		prot |= HV_PCI_MAP_ATTR_WRITE;
 
-	err = fill_sg(entry, pdev, sglist, used, nelems, prot);
+	err = fill_sg(entry, dev, sglist, used, nelems, prot);
 	if (unlikely(err < 0L))
 		goto iommu_map_failed;
 
@@ -526,13 +533,14 @@ bad:
 
 iommu_map_failed:
 	spin_lock_irqsave(&iommu->lock, flags);
-	pci_arena_free(&iommu->arena, entry, npages);
+	arena_free(&iommu->arena, entry, npages);
 	spin_unlock_irqrestore(&iommu->lock, flags);
 
 	return 0;
 }
 
-static void pci_4v_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
+static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist,
+			    int nelems, enum dma_data_direction direction)
 {
 	struct pci_pbm_info *pbm;
 	struct iommu *iommu;
@@ -540,13 +548,13 @@ static void pci_4v_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in
 	long entry;
 	u32 devhandle, bus_addr;
 
-	if (unlikely(direction == PCI_DMA_NONE)) {
+	if (unlikely(direction == DMA_NONE)) {
 		if (printk_ratelimit())
 			WARN_ON(1);
 	}
 
-	iommu = pdev->dev.archdata.iommu;
-	pbm = pdev->dev.archdata.host_controller;
+	iommu = dev->archdata.iommu;
+	pbm = dev->archdata.host_controller;
 	devhandle = pbm->devhandle;
 	
 	bus_addr = sglist->dma_address & IO_PAGE_MASK;
@@ -562,7 +570,7 @@ static void pci_4v_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in
 
 	spin_lock_irqsave(&iommu->lock, flags);
 
-	pci_arena_free(&iommu->arena, entry, npages);
+	arena_free(&iommu->arena, entry, npages);
 
 	do {
 		unsigned long num;
@@ -576,25 +584,29 @@ static void pci_4v_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, in
 	spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
-static void pci_4v_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int direction)
+static void dma_4v_sync_single_for_cpu(struct device *dev,
+				       dma_addr_t bus_addr, size_t sz,
+				       enum dma_data_direction direction)
 {
 	/* Nothing to do... */
 }
 
-static void pci_4v_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction)
+static void dma_4v_sync_sg_for_cpu(struct device *dev,
+				   struct scatterlist *sglist, int nelems,
+				   enum dma_data_direction direction)
 {
 	/* Nothing to do... */
 }
 
-const struct pci_iommu_ops pci_sun4v_iommu_ops = {
-	.alloc_consistent		= pci_4v_alloc_consistent,
-	.free_consistent		= pci_4v_free_consistent,
-	.map_single			= pci_4v_map_single,
-	.unmap_single			= pci_4v_unmap_single,
-	.map_sg				= pci_4v_map_sg,
-	.unmap_sg			= pci_4v_unmap_sg,
-	.dma_sync_single_for_cpu	= pci_4v_dma_sync_single_for_cpu,
-	.dma_sync_sg_for_cpu		= pci_4v_dma_sync_sg_for_cpu,
+const struct dma_ops sun4v_dma_ops = {
+	.alloc_coherent			= dma_4v_alloc_coherent,
+	.free_coherent			= dma_4v_free_coherent,
+	.map_single			= dma_4v_map_single,
+	.unmap_single			= dma_4v_unmap_single,
+	.map_sg				= dma_4v_map_sg,
+	.unmap_sg			= dma_4v_unmap_sg,
+	.sync_single_for_cpu		= dma_4v_sync_single_for_cpu,
+	.sync_sg_for_cpu		= dma_4v_sync_sg_for_cpu,
 };
 
 static void pci_sun4v_scan_bus(struct pci_pbm_info *pbm)
@@ -1186,6 +1198,8 @@ void __init sun4v_pci_init(struct device_node *dp, char *model_name)
 		}
 		printk("SUN4V_PCI: Registered hvapi major[%lu] minor[%lu]\n",
 		       vpci_major, vpci_minor);
+
+		dma_ops = &sun4v_dma_ops;
 	}
 
 	prop = of_find_property(dp, "reg", NULL);
@@ -1206,7 +1220,7 @@ void __init sun4v_pci_init(struct device_node *dp, char *model_name)
 		if (!page)
 			goto fatal_memory_error;
 
-		per_cpu(pci_iommu_batch, i).pglist = (u64 *) page;
+		per_cpu(iommu_batch, i).pglist = (u64 *) page;
 	}
 
 	p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC);

+ 24 - 544
arch/sparc64/kernel/sbus.c

@@ -26,11 +26,6 @@
 
 #define MAP_BASE	((u32)0xc0000000)
 
-struct sbus_info {
-	struct iommu	iommu;
-	struct strbuf	strbuf;
-};
-
 /* Offsets from iommu_regs */
 #define SYSIO_IOMMUREG_BASE	0x2400UL
 #define IOMMU_CONTROL	(0x2400UL - 0x2400UL)	/* IOMMU control register */
@@ -44,19 +39,6 @@ struct sbus_info {
 
 #define IOMMU_DRAM_VALID	(1UL << 30UL)
 
-static void __iommu_flushall(struct iommu *iommu)
-{
-	unsigned long tag;
-	int entry;
-
-	tag = iommu->iommu_control + (IOMMU_TAGDIAG - IOMMU_CONTROL);
-	for (entry = 0; entry < 16; entry++) {
-		upa_writeq(0, tag);
-		tag += 8UL;
-	}
-	upa_readq(iommu->write_complete_reg);
-}
-
 /* Offsets from strbuf_regs */
 #define SYSIO_STRBUFREG_BASE	0x2800UL
 #define STRBUF_CONTROL	(0x2800UL - 0x2800UL)	/* Control */
@@ -69,511 +51,10 @@ static void __iommu_flushall(struct iommu *iommu)
 
 #define STRBUF_TAG_VALID	0x02UL
 
-static void sbus_strbuf_flush(struct iommu *iommu, struct strbuf *strbuf, u32 base, unsigned long npages, int direction)
-{
-	unsigned long n;
-	int limit;
-
-	n = npages;
-	while (n--)
-		upa_writeq(base + (n << IO_PAGE_SHIFT), strbuf->strbuf_pflush);
-
-	/* If the device could not have possibly put dirty data into
-	 * the streaming cache, no flush-flag synchronization needs
-	 * to be performed.
-	 */
-	if (direction == SBUS_DMA_TODEVICE)
-		return;
-
-	*(strbuf->strbuf_flushflag) = 0UL;
-
-	/* Whoopee cushion! */
-	upa_writeq(strbuf->strbuf_flushflag_pa, strbuf->strbuf_fsync);
-	upa_readq(iommu->write_complete_reg);
-
-	limit = 100000;
-	while (*(strbuf->strbuf_flushflag) == 0UL) {
-		limit--;
-		if (!limit)
-			break;
-		udelay(1);
-		rmb();
-	}
-	if (!limit)
-		printk(KERN_WARNING "sbus_strbuf_flush: flushflag timeout "
-		       "vaddr[%08x] npages[%ld]\n",
-		       base, npages);
-}
-
-/* Based largely upon the ppc64 iommu allocator.  */
-static long sbus_arena_alloc(struct iommu *iommu, unsigned long npages)
-{
-	struct iommu_arena *arena = &iommu->arena;
-	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;
-			__iommu_flushall(iommu);
-			pass++;
-			goto again;
-		} else {
-			/* Scanned the whole thing, give up. */
-			return -1;
-		}
-	}
-
-	for (i = n; i < end; i++) {
-		if (test_bit(i, arena->map)) {
-			start = i + 1;
-			goto again;
-		}
-	}
-
-	for (i = n; i < end; i++)
-		__set_bit(i, arena->map);
-
-	arena->hint = end;
-
-	return n;
-}
-
-static void sbus_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 sbus_iommu_table_init(struct iommu *iommu, unsigned int tsbsize)
-{
-	unsigned long tsbbase, order, sz, num_tsb_entries;
-
-	num_tsb_entries = tsbsize / sizeof(iopte_t);
-
-	/* Setup initial software IOMMU state. */
-	spin_lock_init(&iommu->lock);
-	iommu->page_table_map_base = MAP_BASE;
-
-	/* Allocate and initialize the free area map.  */
-	sz = num_tsb_entries / 8;
-	sz = (sz + 7UL) & ~7UL;
-	iommu->arena.map = kzalloc(sz, GFP_KERNEL);
-	if (!iommu->arena.map) {
-		prom_printf("SBUS_IOMMU: Error, kmalloc(arena.map) failed.\n");
-		prom_halt();
-	}
-	iommu->arena.limit = num_tsb_entries;
-
-	/* Now allocate and setup the IOMMU page table itself.  */
-	order = get_order(tsbsize);
-	tsbbase = __get_free_pages(GFP_KERNEL, order);
-	if (!tsbbase) {
-		prom_printf("IOMMU: Error, gfp(tsb) failed.\n");
-		prom_halt();
-	}
-	iommu->page_table = (iopte_t *)tsbbase;
-	memset(iommu->page_table, 0, tsbsize);
-}
-
-static inline iopte_t *alloc_npages(struct iommu *iommu, unsigned long npages)
-{
-	long entry;
-
-	entry = sbus_arena_alloc(iommu, npages);
-	if (unlikely(entry < 0))
-		return NULL;
-
-	return iommu->page_table + entry;
-}
-
-static inline void free_npages(struct iommu *iommu, dma_addr_t base, unsigned long npages)
-{
-	sbus_arena_free(&iommu->arena, base >> IO_PAGE_SHIFT, npages);
-}
-
-void *sbus_alloc_consistent(struct sbus_dev *sdev, size_t size, dma_addr_t *dvma_addr)
-{
-	struct sbus_info *info;
-	struct iommu *iommu;
-	iopte_t *iopte;
-	unsigned long flags, order, first_page;
-	void *ret;
-	int npages;
-
-	size = IO_PAGE_ALIGN(size);
-	order = get_order(size);
-	if (order >= 10)
-		return NULL;
-
-	first_page = __get_free_pages(GFP_KERNEL|__GFP_COMP, order);
-	if (first_page == 0UL)
-		return NULL;
-	memset((char *)first_page, 0, PAGE_SIZE << order);
-
-	info = sdev->bus->iommu;
-	iommu = &info->iommu;
-
-	spin_lock_irqsave(&iommu->lock, flags);
-	iopte = alloc_npages(iommu, size >> IO_PAGE_SHIFT);
-	spin_unlock_irqrestore(&iommu->lock, flags);
-
-	if (unlikely(iopte == NULL)) {
-		free_pages(first_page, order);
-		return NULL;
-	}
-
-	*dvma_addr = (iommu->page_table_map_base +
-		      ((iopte - iommu->page_table) << IO_PAGE_SHIFT));
-	ret = (void *) first_page;
-	npages = size >> IO_PAGE_SHIFT;
-	first_page = __pa(first_page);
-	while (npages--) {
-		iopte_val(*iopte) = (IOPTE_VALID | IOPTE_CACHE |
-				     IOPTE_WRITE |
-				     (first_page & IOPTE_PAGE));
-		iopte++;
-		first_page += IO_PAGE_SIZE;
-	}
-
-	return ret;
-}
-
-void sbus_free_consistent(struct sbus_dev *sdev, size_t size, void *cpu, dma_addr_t dvma)
-{
-	struct sbus_info *info;
-	struct iommu *iommu;
-	iopte_t *iopte;
-	unsigned long flags, order, npages;
-
-	npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT;
-	info = sdev->bus->iommu;
-	iommu = &info->iommu;
-	iopte = iommu->page_table +
-		((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
-
-	spin_lock_irqsave(&iommu->lock, flags);
-
-	free_npages(iommu, dvma - iommu->page_table_map_base, npages);
-
-	spin_unlock_irqrestore(&iommu->lock, flags);
-
-	order = get_order(size);
-	if (order < 10)
-		free_pages((unsigned long)cpu, order);
-}
-
-dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, size_t sz, int direction)
-{
-	struct sbus_info *info;
-	struct iommu *iommu;
-	iopte_t *base;
-	unsigned long flags, npages, oaddr;
-	unsigned long i, base_paddr;
-	u32 bus_addr, ret;
-	unsigned long iopte_protection;
-
-	info = sdev->bus->iommu;
-	iommu = &info->iommu;
-
-	if (unlikely(direction == SBUS_DMA_NONE))
-		BUG();
-
-	oaddr = (unsigned long)ptr;
-	npages = IO_PAGE_ALIGN(oaddr + sz) - (oaddr & IO_PAGE_MASK);
-	npages >>= IO_PAGE_SHIFT;
-
-	spin_lock_irqsave(&iommu->lock, flags);
-	base = alloc_npages(iommu, npages);
-	spin_unlock_irqrestore(&iommu->lock, flags);
-
-	if (unlikely(!base))
-		BUG();
-
-	bus_addr = (iommu->page_table_map_base +
-		    ((base - iommu->page_table) << IO_PAGE_SHIFT));
-	ret = bus_addr | (oaddr & ~IO_PAGE_MASK);
-	base_paddr = __pa(oaddr & IO_PAGE_MASK);
-
-	iopte_protection = IOPTE_VALID | IOPTE_STBUF | IOPTE_CACHE;
-	if (direction != SBUS_DMA_TODEVICE)
-		iopte_protection |= IOPTE_WRITE;
-
-	for (i = 0; i < npages; i++, base++, base_paddr += IO_PAGE_SIZE)
-		iopte_val(*base) = iopte_protection | base_paddr;
-
-	return ret;
-}
-
-void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t bus_addr, size_t sz, int direction)
-{
-	struct sbus_info *info = sdev->bus->iommu;
-	struct iommu *iommu = &info->iommu;
-	struct strbuf *strbuf = &info->strbuf;
-	iopte_t *base;
-	unsigned long flags, npages, i;
-
-	if (unlikely(direction == SBUS_DMA_NONE))
-		BUG();
-
-	npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK);
-	npages >>= IO_PAGE_SHIFT;
-	base = iommu->page_table +
-		((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
-
-	bus_addr &= IO_PAGE_MASK;
-
-	spin_lock_irqsave(&iommu->lock, flags);
-	sbus_strbuf_flush(iommu, strbuf, bus_addr, npages, direction);
-	for (i = 0; i < npages; i++)
-		iopte_val(base[i]) = 0UL;
-	free_npages(iommu, bus_addr - iommu->page_table_map_base, npages);
-	spin_unlock_irqrestore(&iommu->lock, flags);
-}
-
-#define SG_ENT_PHYS_ADDRESS(SG)	\
-	(__pa(page_address((SG)->page)) + (SG)->offset)
-
-static inline void fill_sg(iopte_t *iopte, struct scatterlist *sg,
-			   int nused, int nelems, unsigned long iopte_protection)
-{
-	struct scatterlist *dma_sg = sg;
-	struct scatterlist *sg_end = sg + nelems;
-	int i;
-
-	for (i = 0; i < nused; i++) {
-		unsigned long pteval = ~0UL;
-		u32 dma_npages;
-
-		dma_npages = ((dma_sg->dma_address & (IO_PAGE_SIZE - 1UL)) +
-			      dma_sg->dma_length +
-			      ((IO_PAGE_SIZE - 1UL))) >> IO_PAGE_SHIFT;
-		do {
-			unsigned long offset;
-			signed int len;
-
-			/* If we are here, we know we have at least one
-			 * more page to map.  So walk forward until we
-			 * hit a page crossing, and begin creating new
-			 * mappings from that spot.
-			 */
-			for (;;) {
-				unsigned long tmp;
-
-				tmp = SG_ENT_PHYS_ADDRESS(sg);
-				len = sg->length;
-				if (((tmp ^ pteval) >> IO_PAGE_SHIFT) != 0UL) {
-					pteval = tmp & IO_PAGE_MASK;
-					offset = tmp & (IO_PAGE_SIZE - 1UL);
-					break;
-				}
-				if (((tmp ^ (tmp + len - 1UL)) >> IO_PAGE_SHIFT) != 0UL) {
-					pteval = (tmp + IO_PAGE_SIZE) & IO_PAGE_MASK;
-					offset = 0UL;
-					len -= (IO_PAGE_SIZE - (tmp & (IO_PAGE_SIZE - 1UL)));
-					break;
-				}
-				sg++;
-			}
-
-			pteval = iopte_protection | (pteval & IOPTE_PAGE);
-			while (len > 0) {
-				*iopte++ = __iopte(pteval);
-				pteval += IO_PAGE_SIZE;
-				len -= (IO_PAGE_SIZE - offset);
-				offset = 0;
-				dma_npages--;
-			}
-
-			pteval = (pteval & IOPTE_PAGE) + len;
-			sg++;
-
-			/* Skip over any tail mappings we've fully mapped,
-			 * adjusting pteval along the way.  Stop when we
-			 * detect a page crossing event.
-			 */
-			while (sg < sg_end &&
-			       (pteval << (64 - IO_PAGE_SHIFT)) != 0UL &&
-			       (pteval == SG_ENT_PHYS_ADDRESS(sg)) &&
-			       ((pteval ^
-				 (SG_ENT_PHYS_ADDRESS(sg) + sg->length - 1UL)) >> IO_PAGE_SHIFT) == 0UL) {
-				pteval += sg->length;
-				sg++;
-			}
-			if ((pteval << (64 - IO_PAGE_SHIFT)) == 0UL)
-				pteval = ~0UL;
-		} while (dma_npages != 0);
-		dma_sg++;
-	}
-}
-
-int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sglist, int nelems, int direction)
-{
-	struct sbus_info *info;
-	struct iommu *iommu;
-	unsigned long flags, npages, iopte_protection;
-	iopte_t *base;
-	u32 dma_base;
-	struct scatterlist *sgtmp;
-	int used;
-
-	/* Fast path single entry scatterlists. */
-	if (nelems == 1) {
-		sglist->dma_address =
-			sbus_map_single(sdev,
-					(page_address(sglist->page) + sglist->offset),
-					sglist->length, direction);
-		sglist->dma_length = sglist->length;
-		return 1;
-	}
-
-	info = sdev->bus->iommu;
-	iommu = &info->iommu;
-
-	if (unlikely(direction == SBUS_DMA_NONE))
-		BUG();
-
-	npages = prepare_sg(sglist, nelems);
-
-	spin_lock_irqsave(&iommu->lock, flags);
-	base = alloc_npages(iommu, npages);
-	spin_unlock_irqrestore(&iommu->lock, flags);
-
-	if (unlikely(base == NULL))
-		BUG();
-
-	dma_base = iommu->page_table_map_base +
-		((base - iommu->page_table) << IO_PAGE_SHIFT);
-
-	/* Normalize DVMA addresses. */
-	used = nelems;
-
-	sgtmp = sglist;
-	while (used && sgtmp->dma_length) {
-		sgtmp->dma_address += dma_base;
-		sgtmp++;
-		used--;
-	}
-	used = nelems - used;
-
-	iopte_protection = IOPTE_VALID | IOPTE_STBUF | IOPTE_CACHE;
-	if (direction != SBUS_DMA_TODEVICE)
-		iopte_protection |= IOPTE_WRITE;
-
-	fill_sg(base, sglist, used, nelems, iopte_protection);
-
-#ifdef VERIFY_SG
-	verify_sglist(sglist, nelems, base, npages);
-#endif
-
-	return used;
-}
-
-void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sglist, int nelems, int direction)
-{
-	struct sbus_info *info;
-	struct iommu *iommu;
-	struct strbuf *strbuf;
-	iopte_t *base;
-	unsigned long flags, i, npages;
-	u32 bus_addr;
-
-	if (unlikely(direction == SBUS_DMA_NONE))
-		BUG();
-
-	info = sdev->bus->iommu;
-	iommu = &info->iommu;
-	strbuf = &info->strbuf;
-
-	bus_addr = sglist->dma_address & IO_PAGE_MASK;
-
-	for (i = 1; i < nelems; i++)
-		if (sglist[i].dma_length == 0)
-			break;
-	i--;
-	npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length) -
-		  bus_addr) >> IO_PAGE_SHIFT;
-
-	base = iommu->page_table +
-		((bus_addr - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
-
-	spin_lock_irqsave(&iommu->lock, flags);
-	sbus_strbuf_flush(iommu, strbuf, bus_addr, npages, direction);
-	for (i = 0; i < npages; i++)
-		iopte_val(base[i]) = 0UL;
-	free_npages(iommu, bus_addr - iommu->page_table_map_base, npages);
-	spin_unlock_irqrestore(&iommu->lock, flags);
-}
-
-void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev, dma_addr_t bus_addr, size_t sz, int direction)
-{
-	struct sbus_info *info;
-	struct iommu *iommu;
-	struct strbuf *strbuf;
-	unsigned long flags, npages;
-
-	info = sdev->bus->iommu;
-	iommu = &info->iommu;
-	strbuf = &info->strbuf;
-
-	npages = IO_PAGE_ALIGN(bus_addr + sz) - (bus_addr & IO_PAGE_MASK);
-	npages >>= IO_PAGE_SHIFT;
-	bus_addr &= IO_PAGE_MASK;
-
-	spin_lock_irqsave(&iommu->lock, flags);
-	sbus_strbuf_flush(iommu, strbuf, bus_addr, npages, direction);
-	spin_unlock_irqrestore(&iommu->lock, flags);
-}
-
-void sbus_dma_sync_single_for_device(struct sbus_dev *sdev, dma_addr_t base, size_t size, int direction)
-{
-}
-
-void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev, struct scatterlist *sglist, int nelems, int direction)
-{
-	struct sbus_info *info;
-	struct iommu *iommu;
-	struct strbuf *strbuf;
-	unsigned long flags, npages, i;
-	u32 bus_addr;
-
-	info = sdev->bus->iommu;
-	iommu = &info->iommu;
-	strbuf = &info->strbuf;
-
-	bus_addr = sglist[0].dma_address & IO_PAGE_MASK;
-	for (i = 0; i < nelems; i++) {
-		if (!sglist[i].dma_length)
-			break;
-	}
-	i--;
-	npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length)
-		  - bus_addr) >> IO_PAGE_SHIFT;
-
-	spin_lock_irqsave(&iommu->lock, flags);
-	sbus_strbuf_flush(iommu, strbuf, bus_addr, npages, direction);
-	spin_unlock_irqrestore(&iommu->lock, flags);
-}
-
-void sbus_dma_sync_sg_for_device(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int direction)
-{
-}
-
 /* Enable 64-bit DVMA mode for the given device. */
 void sbus_set_sbus64(struct sbus_dev *sdev, int bursts)
 {
-	struct sbus_info *info = sdev->bus->iommu;
-	struct iommu *iommu = &info->iommu;
+	struct iommu *iommu = sdev->ofdev.dev.archdata.iommu;
 	int slot = sdev->slot;
 	unsigned long cfg_reg;
 	u64 val;
@@ -713,8 +194,7 @@ static unsigned long sysio_imap_to_iclr(unsigned long imap)
 unsigned int sbus_build_irq(void *buscookie, unsigned int ino)
 {
 	struct sbus_bus *sbus = (struct sbus_bus *)buscookie;
-	struct sbus_info *info = sbus->iommu;
-	struct iommu *iommu = &info->iommu;
+	struct iommu *iommu = sbus->ofdev.dev.archdata.iommu;
 	unsigned long reg_base = iommu->write_complete_reg - 0x2000UL;
 	unsigned long imap, iclr;
 	int sbus_level = 0;
@@ -776,8 +256,7 @@ unsigned int sbus_build_irq(void *buscookie, unsigned int ino)
 static irqreturn_t sysio_ue_handler(int irq, void *dev_id)
 {
 	struct sbus_bus *sbus = dev_id;
-	struct sbus_info *info = sbus->iommu;
-	struct iommu *iommu = &info->iommu;
+	struct iommu *iommu = sbus->ofdev.dev.archdata.iommu;
 	unsigned long reg_base = iommu->write_complete_reg - 0x2000UL;
 	unsigned long afsr_reg, afar_reg;
 	unsigned long afsr, afar, error_bits;
@@ -849,8 +328,7 @@ static irqreturn_t sysio_ue_handler(int irq, void *dev_id)
 static irqreturn_t sysio_ce_handler(int irq, void *dev_id)
 {
 	struct sbus_bus *sbus = dev_id;
-	struct sbus_info *info = sbus->iommu;
-	struct iommu *iommu = &info->iommu;
+	struct iommu *iommu = sbus->ofdev.dev.archdata.iommu;
 	unsigned long reg_base = iommu->write_complete_reg - 0x2000UL;
 	unsigned long afsr_reg, afar_reg;
 	unsigned long afsr, afar, error_bits;
@@ -927,8 +405,7 @@ static irqreturn_t sysio_ce_handler(int irq, void *dev_id)
 static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id)
 {
 	struct sbus_bus *sbus = dev_id;
-	struct sbus_info *info = sbus->iommu;
-	struct iommu *iommu = &info->iommu;
+	struct iommu *iommu = sbus->ofdev.dev.archdata.iommu;
 	unsigned long afsr_reg, afar_reg, reg_base;
 	unsigned long afsr, afar, error_bits;
 	int reported;
@@ -995,8 +472,7 @@ static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id)
 
 static void __init sysio_register_error_handlers(struct sbus_bus *sbus)
 {
-	struct sbus_info *info = sbus->iommu;
-	struct iommu *iommu = &info->iommu;
+	struct iommu *iommu = sbus->ofdev.dev.archdata.iommu;
 	unsigned long reg_base = iommu->write_complete_reg - 0x2000UL;
 	unsigned int irq;
 	u64 control;
@@ -1041,7 +517,6 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus)
 {
 	const struct linux_prom64_registers *pr;
 	struct device_node *dp;
-	struct sbus_info *info;
 	struct iommu *iommu;
 	struct strbuf *strbuf;
 	unsigned long regs, reg_base;
@@ -1054,25 +529,28 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus)
 
 	pr = of_get_property(dp, "reg", NULL);
 	if (!pr) {
-		prom_printf("sbus_iommu_init: Cannot map SYSIO control registers.\n");
+		prom_printf("sbus_iommu_init: Cannot map SYSIO "
+			    "control registers.\n");
 		prom_halt();
 	}
 	regs = pr->phys_addr;
 
-	info = kzalloc(sizeof(*info), GFP_ATOMIC);
-	if (info == NULL) {
-		prom_printf("sbus_iommu_init: Fatal error, "
-			    "kmalloc(info) failed\n");
-		prom_halt();
-	}
+	iommu = kzalloc(sizeof(*iommu), GFP_ATOMIC);
+	if (!iommu)
+		goto fatal_memory_error;
+	strbuf = kzalloc(sizeof(*strbuf), GFP_ATOMIC);
+	if (!strbuf)
+		goto fatal_memory_error;
 
-	iommu = &info->iommu;
-	strbuf = &info->strbuf;
+	sbus->ofdev.dev.archdata.iommu = iommu;
+	sbus->ofdev.dev.archdata.stc = strbuf;
 
 	reg_base = regs + SYSIO_IOMMUREG_BASE;
 	iommu->iommu_control = reg_base + IOMMU_CONTROL;
 	iommu->iommu_tsbbase = reg_base + IOMMU_TSBBASE;
 	iommu->iommu_flush = reg_base + IOMMU_FLUSH;
+	iommu->iommu_tags = iommu->iommu_control +
+		(IOMMU_TAGDIAG - IOMMU_CONTROL);
 
 	reg_base = regs + SYSIO_STRBUFREG_BASE;
 	strbuf->strbuf_control = reg_base + STRBUF_CONTROL;
@@ -1093,14 +571,12 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus)
 	 */
 	iommu->write_complete_reg = regs + 0x2000UL;
 
-	/* Link into SYSIO software state. */
-	sbus->iommu = info;
-
 	printk("SYSIO: UPA portID %x, at %016lx\n",
 	       sbus->portid, regs);
 
 	/* Setup for TSB_SIZE=7, TBW_SIZE=0, MMU_DE=1, MMU_EN=1 */
-	sbus_iommu_table_init(iommu, IO_TSB_SIZE);
+	if (iommu_table_init(iommu, IO_TSB_SIZE, MAP_BASE, 0xffffffff))
+		goto fatal_memory_error;
 
 	control = upa_readq(iommu->iommu_control);
 	control = ((7UL << 16UL)	|
@@ -1157,6 +633,10 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus)
 		starfire_hookup(sbus->portid);
 
 	sysio_register_error_handlers(sbus);
+	return;
+
+fatal_memory_error:
+	prom_printf("sbus_iommu_init: Fatal memory allocation error.\n");
 }
 
 void sbus_fill_device_irq(struct sbus_dev *sdev)

+ 75 - 0
arch/sparc64/kernel/time.c

@@ -1460,6 +1460,74 @@ static int cmos_set_rtc_time(struct rtc_time *rtc_tm)
 }
 #endif /* CONFIG_PCI */
 
+static void mostek_get_rtc_time(struct rtc_time *rtc_tm)
+{
+	void __iomem *regs = mstk48t02_regs;
+	u8 tmp;
+
+	spin_lock_irq(&mostek_lock);
+
+	tmp = mostek_read(regs + MOSTEK_CREG);
+	tmp |= MSTK_CREG_READ;
+	mostek_write(regs + MOSTEK_CREG, tmp);
+
+	rtc_tm->tm_sec = MSTK_REG_SEC(regs);
+	rtc_tm->tm_min = MSTK_REG_MIN(regs);
+	rtc_tm->tm_hour = MSTK_REG_HOUR(regs);
+	rtc_tm->tm_mday = MSTK_REG_DOM(regs);
+	rtc_tm->tm_mon = MSTK_REG_MONTH(regs);
+	rtc_tm->tm_year = MSTK_CVT_YEAR( MSTK_REG_YEAR(regs) );
+	rtc_tm->tm_wday = MSTK_REG_DOW(regs);
+
+	tmp = mostek_read(regs + MOSTEK_CREG);
+	tmp &= ~MSTK_CREG_READ;
+	mostek_write(regs + MOSTEK_CREG, tmp);
+
+	spin_unlock_irq(&mostek_lock);
+
+	rtc_tm->tm_mon--;
+	rtc_tm->tm_wday--;
+	rtc_tm->tm_year -= 1900;
+}
+
+static int mostek_set_rtc_time(struct rtc_time *rtc_tm)
+{
+	unsigned char mon, day, hrs, min, sec, wday;
+	void __iomem *regs = mstk48t02_regs;
+	unsigned int yrs;
+	u8 tmp;
+
+	yrs = rtc_tm->tm_year + 1900;
+	mon = rtc_tm->tm_mon + 1;
+	day = rtc_tm->tm_mday;
+	wday = rtc_tm->tm_wday + 1;
+	hrs = rtc_tm->tm_hour;
+	min = rtc_tm->tm_min;
+	sec = rtc_tm->tm_sec;
+
+	spin_lock_irq(&mostek_lock);
+
+	tmp = mostek_read(regs + MOSTEK_CREG);
+	tmp |= MSTK_CREG_WRITE;
+	mostek_write(regs + MOSTEK_CREG, tmp);
+
+	MSTK_SET_REG_SEC(regs, sec);
+	MSTK_SET_REG_MIN(regs, min);
+	MSTK_SET_REG_HOUR(regs, hrs);
+	MSTK_SET_REG_DOW(regs, wday);
+	MSTK_SET_REG_DOM(regs, day);
+	MSTK_SET_REG_MONTH(regs, mon);
+	MSTK_SET_REG_YEAR(regs, yrs - MSTK_YEAR_ZERO);
+
+	tmp = mostek_read(regs + MOSTEK_CREG);
+	tmp &= ~MSTK_CREG_WRITE;
+	mostek_write(regs + MOSTEK_CREG, tmp);
+
+	spin_unlock_irq(&mostek_lock);
+
+	return 0;
+}
+
 struct mini_rtc_ops {
 	void (*get_rtc_time)(struct rtc_time *);
 	int (*set_rtc_time)(struct rtc_time *);
@@ -1487,6 +1555,11 @@ static struct mini_rtc_ops cmos_rtc_ops = {
 };
 #endif /* CONFIG_PCI */
 
+static struct mini_rtc_ops mostek_rtc_ops = {
+	.get_rtc_time = mostek_get_rtc_time,
+	.set_rtc_time = mostek_set_rtc_time,
+};
+
 static struct mini_rtc_ops *mini_rtc_ops;
 
 static inline void mini_get_rtc_time(struct rtc_time *time)
@@ -1615,6 +1688,8 @@ static int __init rtc_mini_init(void)
 	else if (ds1287_regs)
 		mini_rtc_ops = &cmos_rtc_ops;
 #endif /* CONFIG_PCI */
+	else if (mstk48t02_regs)
+		mini_rtc_ops = &mostek_rtc_ops;
 	else
 		return -ENODEV;
 

+ 11 - 7
arch/sparc64/kernel/traps.c

@@ -2134,12 +2134,20 @@ static void user_instruction_dump (unsigned int __user *pc)
 void show_stack(struct task_struct *tsk, unsigned long *_ksp)
 {
 	unsigned long pc, fp, thread_base, ksp;
-	void *tp = task_stack_page(tsk);
+	struct thread_info *tp;
 	struct reg_window *rw;
 	int count = 0;
 
 	ksp = (unsigned long) _ksp;
-
+	if (!tsk)
+		tsk = current;
+	tp = task_thread_info(tsk);
+	if (ksp == 0UL) {
+		if (tsk == current)
+			asm("mov %%fp, %0" : "=r" (ksp));
+		else
+			ksp = tp->ksp;
+	}
 	if (tp == current_thread_info())
 		flushw_all();
 
@@ -2168,11 +2176,7 @@ void show_stack(struct task_struct *tsk, unsigned long *_ksp)
 
 void dump_stack(void)
 {
-	unsigned long *ksp;
-
-	__asm__ __volatile__("mov	%%fp, %0"
-			     : "=r" (ksp));
-	show_stack(current, ksp);
+	show_stack(current, NULL);
 }
 
 EXPORT_SYMBOL(dump_stack);

+ 1 - 4
arch/sparc64/mm/fault.c

@@ -112,15 +112,12 @@ static void __kprobes unhandled_fault(unsigned long address,
 
 static void bad_kernel_pc(struct pt_regs *regs, unsigned long vaddr)
 {
-	unsigned long *ksp;
-
 	printk(KERN_CRIT "OOPS: Bogus kernel PC [%016lx] in fault handler\n",
 	       regs->tpc);
 	printk(KERN_CRIT "OOPS: RPC [%016lx]\n", regs->u_regs[15]);
 	print_symbol("RPC: <%s>\n", regs->u_regs[15]);
 	printk(KERN_CRIT "OOPS: Fault was to vaddr[%lx]\n", vaddr);
-	__asm__("mov %%sp, %0" : "=r" (ksp));
-	show_stack(current, ksp);
+	dump_stack();
 	unhandled_fault(regs->tpc, current, regs);
 }
 

+ 9 - 0
drivers/sbus/sbus.c

@@ -210,6 +210,10 @@ static void __init walk_children(struct device_node *dp, struct sbus_dev *parent
 
 			sdev->bus = sbus;
 			sdev->parent = parent;
+			sdev->ofdev.dev.archdata.iommu =
+				sbus->ofdev.dev.archdata.iommu;
+			sdev->ofdev.dev.archdata.stc =
+				sbus->ofdev.dev.archdata.stc;
 
 			fill_sbus_device(dp, sdev);
 
@@ -269,6 +273,11 @@ static void __init build_one_sbus(struct device_node *dp, int num_sbus)
 
 			sdev->bus = sbus;
 			sdev->parent = NULL;
+			sdev->ofdev.dev.archdata.iommu =
+				sbus->ofdev.dev.archdata.iommu;
+			sdev->ofdev.dev.archdata.stc =
+				sbus->ofdev.dev.archdata.stc;
+
 			fill_sbus_device(dev_dp, sdev);
 
 			walk_children(dev_dp, sdev, sbus);

+ 53 - 52
drivers/video/bw2.c

@@ -279,90 +279,91 @@ static void __devinit bw2_do_default_mode(struct bw2_par *par,
 	}
 }
 
-struct all_info {
-	struct fb_info info;
-	struct bw2_par par;
-};
-
-static int __devinit bw2_init_one(struct of_device *op)
+static int __devinit bw2_probe(struct of_device *op, const struct of_device_id *match)
 {
 	struct device_node *dp = op->node;
-	struct all_info *all;
+	struct fb_info *info;
+	struct bw2_par *par;
 	int linebytes, err;
 
-	all = kzalloc(sizeof(*all), GFP_KERNEL);
-	if (!all)
-		return -ENOMEM;
+	info = framebuffer_alloc(sizeof(struct bw2_par), &op->dev);
 
-	spin_lock_init(&all->par.lock);
+	err = -ENOMEM;
+	if (!info)
+		goto out_err;
+	par = info->par;
 
-	all->par.physbase = op->resource[0].start;
-	all->par.which_io = op->resource[0].flags & IORESOURCE_BITS;
+	spin_lock_init(&par->lock);
 
-	sbusfb_fill_var(&all->info.var, dp->node, 1);
+	par->physbase = op->resource[0].start;
+	par->which_io = op->resource[0].flags & IORESOURCE_BITS;
+
+	sbusfb_fill_var(&info->var, dp->node, 1);
 	linebytes = of_getintprop_default(dp, "linebytes",
-					  all->info.var.xres);
+					  info->var.xres);
 
-	all->info.var.red.length = all->info.var.green.length =
-		all->info.var.blue.length = all->info.var.bits_per_pixel;
-	all->info.var.red.offset = all->info.var.green.offset =
-		all->info.var.blue.offset = 0;
+	info->var.red.length = info->var.green.length =
+		info->var.blue.length = info->var.bits_per_pixel;
+	info->var.red.offset = info->var.green.offset =
+		info->var.blue.offset = 0;
 
-	all->par.regs = of_ioremap(&op->resource[0], BWTWO_REGISTER_OFFSET,
-				   sizeof(struct bw2_regs), "bw2 regs");
+	par->regs = of_ioremap(&op->resource[0], BWTWO_REGISTER_OFFSET,
+			       sizeof(struct bw2_regs), "bw2 regs");
+	if (!par->regs)
+		goto out_release_fb;
 
 	if (!of_find_property(dp, "width", NULL))
-		bw2_do_default_mode(&all->par, &all->info, &linebytes);
+		bw2_do_default_mode(par, info, &linebytes);
 
-	all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
+	par->fbsize = PAGE_ALIGN(linebytes * info->var.yres);
 
-	all->info.flags = FBINFO_DEFAULT;
-	all->info.fbops = &bw2_ops;
+	info->flags = FBINFO_DEFAULT;
+	info->fbops = &bw2_ops;
 
-	all->info.screen_base =
-		of_ioremap(&op->resource[0], 0, all->par.fbsize, "bw2 ram");
-	all->info.par = &all->par;
+	info->screen_base = of_ioremap(&op->resource[0], 0,
+				       par->fbsize, "bw2 ram");
+	if (!info->screen_base)
+		goto out_unmap_regs;
 
-	bw2_blank(0, &all->info);
+	bw2_blank(0, info);
 
-	bw2_init_fix(&all->info, linebytes);
+	bw2_init_fix(info, linebytes);
 
-	err= register_framebuffer(&all->info);
-	if (err < 0) {
-		of_iounmap(&op->resource[0],
-			   all->par.regs, sizeof(struct bw2_regs));
-		of_iounmap(&op->resource[0],
-			   all->info.screen_base, all->par.fbsize);
-		kfree(all);
-		return err;
-	}
+	err = register_framebuffer(info);
+	if (err < 0)
+		goto out_unmap_screen;
 
-	dev_set_drvdata(&op->dev, all);
+	dev_set_drvdata(&op->dev, info);
 
 	printk("%s: bwtwo at %lx:%lx\n",
-	       dp->full_name,
-	       all->par.which_io, all->par.physbase);
+	       dp->full_name, par->which_io, par->physbase);
 
 	return 0;
-}
 
-static int __devinit bw2_probe(struct of_device *dev, const struct of_device_id *match)
-{
-	struct of_device *op = to_of_device(&dev->dev);
+out_unmap_screen:
+	of_iounmap(&op->resource[0], info->screen_base, par->fbsize);
+
+out_unmap_regs:
+	of_iounmap(&op->resource[0], par->regs, sizeof(struct bw2_regs));
+
+out_release_fb:
+	framebuffer_release(info);
 
-	return bw2_init_one(op);
+out_err:
+	return err;
 }
 
 static int __devexit bw2_remove(struct of_device *op)
 {
-	struct all_info *all = dev_get_drvdata(&op->dev);
+	struct fb_info *info = dev_get_drvdata(&op->dev);
+	struct bw2_par *par = info->par;
 
-	unregister_framebuffer(&all->info);
+	unregister_framebuffer(info);
 
-	of_iounmap(&op->resource[0], all->par.regs, sizeof(struct bw2_regs));
-	of_iounmap(&op->resource[0], all->info.screen_base, all->par.fbsize);
+	of_iounmap(&op->resource[0], par->regs, sizeof(struct bw2_regs));
+	of_iounmap(&op->resource[0], info->screen_base, par->fbsize);
 
-	kfree(all);
+	framebuffer_release(info);
 
 	dev_set_drvdata(&op->dev, NULL);
 

+ 72 - 78
drivers/video/cg14.c

@@ -448,81 +448,79 @@ static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] __devinitdata = {
 	{ .size = 0 }
 };
 
-struct all_info {
-	struct fb_info info;
-	struct cg14_par par;
-};
-
-static void cg14_unmap_regs(struct of_device *op, struct all_info *all)
+static void cg14_unmap_regs(struct of_device *op, struct fb_info *info,
+			    struct cg14_par *par)
 {
-	if (all->par.regs)
+	if (par->regs)
 		of_iounmap(&op->resource[0],
-			   all->par.regs, sizeof(struct cg14_regs));
-	if (all->par.clut)
+			   par->regs, sizeof(struct cg14_regs));
+	if (par->clut)
 		of_iounmap(&op->resource[0],
-			   all->par.clut, sizeof(struct cg14_clut));
-	if (all->par.cursor)
+			   par->clut, sizeof(struct cg14_clut));
+	if (par->cursor)
 		of_iounmap(&op->resource[0],
-			   all->par.cursor, sizeof(struct cg14_cursor));
-	if (all->info.screen_base)
+			   par->cursor, sizeof(struct cg14_cursor));
+	if (info->screen_base)
 		of_iounmap(&op->resource[1],
-			   all->info.screen_base, all->par.fbsize);
+			   info->screen_base, par->fbsize);
 }
 
-static int __devinit cg14_init_one(struct of_device *op)
+static int __devinit cg14_probe(struct of_device *op, const struct of_device_id *match)
 {
 	struct device_node *dp = op->node;
-	struct all_info *all;
+	struct fb_info *info;
+	struct cg14_par *par;
 	int is_8mb, linebytes, i, err;
 
-	all = kzalloc(sizeof(*all), GFP_KERNEL);
-	if (!all)
-		return -ENOMEM;
+	info = framebuffer_alloc(sizeof(struct cg14_par), &op->dev);
+
+	err = -ENOMEM;
+	if (!info)
+		goto out_err;
+	par = info->par;
 
-	spin_lock_init(&all->par.lock);
+	spin_lock_init(&par->lock);
 
-	sbusfb_fill_var(&all->info.var, dp->node, 8);
-	all->info.var.red.length = 8;
-	all->info.var.green.length = 8;
-	all->info.var.blue.length = 8;
+	sbusfb_fill_var(&info->var, dp->node, 8);
+	info->var.red.length = 8;
+	info->var.green.length = 8;
+	info->var.blue.length = 8;
 
 	linebytes = of_getintprop_default(dp, "linebytes",
-					  all->info.var.xres);
-	all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
+					  info->var.xres);
+	par->fbsize = PAGE_ALIGN(linebytes * info->var.yres);
 
 	if (!strcmp(dp->parent->name, "sbus") ||
 	    !strcmp(dp->parent->name, "sbi")) {
-		all->par.physbase = op->resource[0].start;
-		all->par.iospace = op->resource[0].flags & IORESOURCE_BITS;
+		par->physbase = op->resource[0].start;
+		par->iospace = op->resource[0].flags & IORESOURCE_BITS;
 	} else {
-		all->par.physbase = op->resource[1].start;
-		all->par.iospace = op->resource[0].flags & IORESOURCE_BITS;
+		par->physbase = op->resource[1].start;
+		par->iospace = op->resource[0].flags & IORESOURCE_BITS;
 	}
 
-	all->par.regs = of_ioremap(&op->resource[0], 0,
-				   sizeof(struct cg14_regs), "cg14 regs");
-	all->par.clut = of_ioremap(&op->resource[0], CG14_CLUT1,
-				   sizeof(struct cg14_clut), "cg14 clut");
-	all->par.cursor = of_ioremap(&op->resource[0], CG14_CURSORREGS,
-				   sizeof(struct cg14_cursor), "cg14 cursor");
+	par->regs = of_ioremap(&op->resource[0], 0,
+			       sizeof(struct cg14_regs), "cg14 regs");
+	par->clut = of_ioremap(&op->resource[0], CG14_CLUT1,
+			       sizeof(struct cg14_clut), "cg14 clut");
+	par->cursor = of_ioremap(&op->resource[0], CG14_CURSORREGS,
+				 sizeof(struct cg14_cursor), "cg14 cursor");
 
-	all->info.screen_base = of_ioremap(&op->resource[1], 0,
-					   all->par.fbsize, "cg14 ram");
+	info->screen_base = of_ioremap(&op->resource[1], 0,
+				       par->fbsize, "cg14 ram");
 
-	if (!all->par.regs || !all->par.clut || !all->par.cursor ||
-	    !all->info.screen_base)
-		cg14_unmap_regs(op, all);
+	if (!par->regs || !par->clut || !par->cursor || !info->screen_base)
+		goto out_unmap_regs;
 
 	is_8mb = (((op->resource[1].end - op->resource[1].start) + 1) ==
 		  (8 * 1024 * 1024));
 
-	BUILD_BUG_ON(sizeof(all->par.mmap_map) != sizeof(__cg14_mmap_map));
+	BUILD_BUG_ON(sizeof(par->mmap_map) != sizeof(__cg14_mmap_map));
 		
-	memcpy(&all->par.mmap_map, &__cg14_mmap_map,
-	       sizeof(all->par.mmap_map));
+	memcpy(&par->mmap_map, &__cg14_mmap_map, sizeof(par->mmap_map));
 
 	for (i = 0; i < CG14_MMAP_ENTRIES; i++) {
-		struct sbus_mmap_map *map = &all->par.mmap_map[i];
+		struct sbus_mmap_map *map = &par->mmap_map[i];
 
 		if (!map->size)
 			break;
@@ -536,59 +534,55 @@ static int __devinit cg14_init_one(struct of_device *op)
 			map->size *= 2;
 	}
 
-	all->par.mode = MDI_8_PIX;
-	all->par.ramsize = (is_8mb ? 0x800000 : 0x400000);
+	par->mode = MDI_8_PIX;
+	par->ramsize = (is_8mb ? 0x800000 : 0x400000);
 
-	all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
-	all->info.fbops = &cg14_ops;
-	all->info.par = &all->par;
+	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+	info->fbops = &cg14_ops;
 
-	__cg14_reset(&all->par);
+	__cg14_reset(par);
 
-	if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
-		cg14_unmap_regs(op, all);
-		kfree(all);
-		return -ENOMEM;
-	}
-	fb_set_cmap(&all->info.cmap, &all->info);
+	if (fb_alloc_cmap(&info->cmap, 256, 0))
+		goto out_unmap_regs;
 
-	cg14_init_fix(&all->info, linebytes, dp);
+	fb_set_cmap(&info->cmap, info);
 
-	err = register_framebuffer(&all->info);
-	if (err < 0) {
-		fb_dealloc_cmap(&all->info.cmap);
-		cg14_unmap_regs(op, all);
-		kfree(all);
-		return err;
-	}
+	cg14_init_fix(info, linebytes, dp);
+
+	err = register_framebuffer(info);
+	if (err < 0)
+		goto out_dealloc_cmap;
 
-	dev_set_drvdata(&op->dev, all);
+	dev_set_drvdata(&op->dev, info);
 
 	printk("%s: cgfourteen at %lx:%lx, %dMB\n",
 	       dp->full_name,
-	       all->par.iospace, all->par.physbase,
-	       all->par.ramsize >> 20);
+	       par->iospace, par->physbase,
+	       par->ramsize >> 20);
 
 	return 0;
-}
 
-static int __devinit cg14_probe(struct of_device *dev, const struct of_device_id *match)
-{
-	struct of_device *op = to_of_device(&dev->dev);
+out_dealloc_cmap:
+	fb_dealloc_cmap(&info->cmap);
+
+out_unmap_regs:
+	cg14_unmap_regs(op, info, par);
 
-	return cg14_init_one(op);
+out_err:
+	return err;
 }
 
 static int __devexit cg14_remove(struct of_device *op)
 {
-	struct all_info *all = dev_get_drvdata(&op->dev);
+	struct fb_info *info = dev_get_drvdata(&op->dev);
+	struct cg14_par *par = info->par;
 
-	unregister_framebuffer(&all->info);
-	fb_dealloc_cmap(&all->info.cmap);
+	unregister_framebuffer(info);
+	fb_dealloc_cmap(&info->cmap);
 
-	cg14_unmap_regs(op, all);
+	cg14_unmap_regs(op, info, par);
 
-	kfree(all);
+	framebuffer_release(info);
 
 	dev_set_drvdata(&op->dev, NULL);
 

+ 67 - 69
drivers/video/cg3.c

@@ -353,104 +353,102 @@ static void __devinit cg3_do_default_mode(struct cg3_par *par)
 	}
 }
 
-struct all_info {
-	struct fb_info info;
-	struct cg3_par par;
-};
-
-static int __devinit cg3_init_one(struct of_device *op)
+static int __devinit cg3_probe(struct of_device *op,
+			       const struct of_device_id *match)
 {
 	struct device_node *dp = op->node;
-	struct all_info *all;
+	struct fb_info *info;
+	struct cg3_par *par;
 	int linebytes, err;
 
-	all = kzalloc(sizeof(*all), GFP_KERNEL);
-	if (!all)
-		return -ENOMEM;
+	info = framebuffer_alloc(sizeof(struct cg3_par), &op->dev);
 
-	spin_lock_init(&all->par.lock);
+	err = -ENOMEM;
+	if (!info)
+		goto out_err;
+	par = info->par;
 
-	all->par.physbase = op->resource[0].start;
-	all->par.which_io = op->resource[0].flags & IORESOURCE_BITS;
+	spin_lock_init(&par->lock);
 
-	sbusfb_fill_var(&all->info.var, dp->node, 8);
-	all->info.var.red.length = 8;
-	all->info.var.green.length = 8;
-	all->info.var.blue.length = 8;
+	par->physbase = op->resource[0].start;
+	par->which_io = op->resource[0].flags & IORESOURCE_BITS;
+
+	sbusfb_fill_var(&info->var, dp->node, 8);
+	info->var.red.length = 8;
+	info->var.green.length = 8;
+	info->var.blue.length = 8;
 	if (!strcmp(dp->name, "cgRDI"))
-		all->par.flags |= CG3_FLAG_RDI;
-	if (all->par.flags & CG3_FLAG_RDI)
-		cg3_rdi_maybe_fixup_var(&all->info.var, dp);
+		par->flags |= CG3_FLAG_RDI;
+	if (par->flags & CG3_FLAG_RDI)
+		cg3_rdi_maybe_fixup_var(&info->var, dp);
 
 	linebytes = of_getintprop_default(dp, "linebytes",
-					  all->info.var.xres);
-	all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
+					  info->var.xres);
+	par->fbsize = PAGE_ALIGN(linebytes * info->var.yres);
 
-	all->par.regs = of_ioremap(&op->resource[0], CG3_REGS_OFFSET,
-				   sizeof(struct cg3_regs), "cg3 regs");
+	par->regs = of_ioremap(&op->resource[0], CG3_REGS_OFFSET,
+			       sizeof(struct cg3_regs), "cg3 regs");
+	if (!par->regs)
+		goto out_release_fb;
 
-	all->info.flags = FBINFO_DEFAULT;
-	all->info.fbops = &cg3_ops;
-	all->info.screen_base =
-		of_ioremap(&op->resource[0], CG3_RAM_OFFSET,
-			   all->par.fbsize, "cg3 ram");
-	all->info.par = &all->par;
+	info->flags = FBINFO_DEFAULT;
+	info->fbops = &cg3_ops;
+	info->screen_base = of_ioremap(&op->resource[0], CG3_RAM_OFFSET,
+				       par->fbsize, "cg3 ram");
+	if (!info->screen_base)
+		goto out_unmap_regs;
 
-	cg3_blank(0, &all->info);
+	cg3_blank(0, info);
 
 	if (!of_find_property(dp, "width", NULL))
-		cg3_do_default_mode(&all->par);
-
-	if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
-		of_iounmap(&op->resource[0],
-			   all->par.regs, sizeof(struct cg3_regs));
-		of_iounmap(&op->resource[0],
-			   all->info.screen_base, all->par.fbsize);
-		kfree(all);
-		return -ENOMEM;
-	}
-	fb_set_cmap(&all->info.cmap, &all->info);
-
-	cg3_init_fix(&all->info, linebytes, dp);
-
-	err = register_framebuffer(&all->info);
-	if (err < 0) {
-		fb_dealloc_cmap(&all->info.cmap);
-		of_iounmap(&op->resource[0],
-			   all->par.regs, sizeof(struct cg3_regs));
-		of_iounmap(&op->resource[0],
-			   all->info.screen_base, all->par.fbsize);
-		kfree(all);
-		return err;
-	}
+		cg3_do_default_mode(par);
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0))
+		goto out_unmap_screen;
+
+	fb_set_cmap(&info->cmap, info);
 
-	dev_set_drvdata(&op->dev, all);
+	cg3_init_fix(info, linebytes, dp);
+
+	err = register_framebuffer(info);
+	if (err < 0)
+		goto out_dealloc_cmap;
+
+	dev_set_drvdata(&op->dev, info);
 
 	printk("%s: cg3 at %lx:%lx\n",
-	       dp->full_name, all->par.which_io, all->par.physbase);
+	       dp->full_name, par->which_io, par->physbase);
 
 	return 0;
-}
 
-static int __devinit cg3_probe(struct of_device *dev,
-			       const struct of_device_id *match)
-{
-	struct of_device *op = to_of_device(&dev->dev);
+out_dealloc_cmap:
+	fb_dealloc_cmap(&info->cmap);
+
+out_unmap_screen:
+	of_iounmap(&op->resource[0], info->screen_base, par->fbsize);
+
+out_unmap_regs:
+	of_iounmap(&op->resource[0], par->regs, sizeof(struct cg3_regs));
+
+out_release_fb:
+	framebuffer_release(info);
 
-	return cg3_init_one(op);
+out_err:
+	return err;
 }
 
 static int __devexit cg3_remove(struct of_device *op)
 {
-	struct all_info *all = dev_get_drvdata(&op->dev);
+	struct fb_info *info = dev_get_drvdata(&op->dev);
+	struct cg3_par *par = info->par;
 
-	unregister_framebuffer(&all->info);
-	fb_dealloc_cmap(&all->info.cmap);
+	unregister_framebuffer(info);
+	fb_dealloc_cmap(&info->cmap);
 
-	of_iounmap(&op->resource[0], all->par.regs, sizeof(struct cg3_regs));
-	of_iounmap(&op->resource[0], all->info.screen_base, all->par.fbsize);
+	of_iounmap(&op->resource[0], par->regs, sizeof(struct cg3_regs));
+	of_iounmap(&op->resource[0], info->screen_base, par->fbsize);
 
-	kfree(all);
+	framebuffer_release(info);
 
 	dev_set_drvdata(&op->dev, NULL);
 

+ 73 - 88
drivers/video/cg6.c

@@ -653,135 +653,120 @@ static void cg6_chip_init(struct fb_info *info)
 	sbus_writel(info->var.yres - 1, &fbc->clipmaxy);
 }
 
-struct all_info {
-	struct fb_info info;
-	struct cg6_par par;
-};
-
-static void cg6_unmap_regs(struct of_device *op, struct all_info *all)
+static void cg6_unmap_regs(struct of_device *op, struct fb_info *info,
+			   struct cg6_par *par)
 {
-	if (all->par.fbc)
-		of_iounmap(&op->resource[0], all->par.fbc, 4096);
-	if (all->par.tec)
-		of_iounmap(&op->resource[0],
-			   all->par.tec, sizeof(struct cg6_tec));
-	if (all->par.thc)
-		of_iounmap(&op->resource[0],
-			   all->par.thc, sizeof(struct cg6_thc));
-	if (all->par.bt)
-		of_iounmap(&op->resource[0],
-			   all->par.bt, sizeof(struct bt_regs));
-	if (all->par.fhc)
-		of_iounmap(&op->resource[0],
-			   all->par.fhc, sizeof(u32));
-
-	if (all->info.screen_base)
-		of_iounmap(&op->resource[0],
-			   all->info.screen_base, all->par.fbsize);
+	if (par->fbc)
+		of_iounmap(&op->resource[0], par->fbc, 4096);
+	if (par->tec)
+		of_iounmap(&op->resource[0], par->tec, sizeof(struct cg6_tec));
+	if (par->thc)
+		of_iounmap(&op->resource[0], par->thc, sizeof(struct cg6_thc));
+	if (par->bt)
+		of_iounmap(&op->resource[0], par->bt, sizeof(struct bt_regs));
+	if (par->fhc)
+		of_iounmap(&op->resource[0], par->fhc, sizeof(u32));
+
+	if (info->screen_base)
+		of_iounmap(&op->resource[0], info->screen_base, par->fbsize);
 }
 
-static int __devinit cg6_init_one(struct of_device *op)
+static int __devinit cg6_probe(struct of_device *op, const struct of_device_id *match)
 {
 	struct device_node *dp = op->node;
-	struct all_info *all;
+	struct fb_info *info;
+	struct cg6_par *par;
 	int linebytes, err;
 
-	all = kzalloc(sizeof(*all), GFP_KERNEL);
-	if (!all)
-		return -ENOMEM;
+	info = framebuffer_alloc(sizeof(struct cg6_par), &op->dev);
+
+	err = -ENOMEM;
+	if (!info)
+		goto out_err;
+	par = info->par;
 
-	spin_lock_init(&all->par.lock);
+	spin_lock_init(&par->lock);
 
-	all->par.physbase = op->resource[0].start;
-	all->par.which_io = op->resource[0].flags & IORESOURCE_BITS;
+	par->physbase = op->resource[0].start;
+	par->which_io = op->resource[0].flags & IORESOURCE_BITS;
 
-	sbusfb_fill_var(&all->info.var, dp->node, 8);
-	all->info.var.red.length = 8;
-	all->info.var.green.length = 8;
-	all->info.var.blue.length = 8;
+	sbusfb_fill_var(&info->var, dp->node, 8);
+	info->var.red.length = 8;
+	info->var.green.length = 8;
+	info->var.blue.length = 8;
 
 	linebytes = of_getintprop_default(dp, "linebytes",
-					  all->info.var.xres);
-	all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
+					  info->var.xres);
+	par->fbsize = PAGE_ALIGN(linebytes * info->var.yres);
 	if (of_find_property(dp, "dblbuf", NULL))
-		all->par.fbsize *= 4;
+		par->fbsize *= 4;
 
-	all->par.fbc = of_ioremap(&op->resource[0], CG6_FBC_OFFSET,
+	par->fbc = of_ioremap(&op->resource[0], CG6_FBC_OFFSET,
 				  4096, "cgsix fbc");
-	all->par.tec = of_ioremap(&op->resource[0], CG6_TEC_OFFSET,
+	par->tec = of_ioremap(&op->resource[0], CG6_TEC_OFFSET,
 				  sizeof(struct cg6_tec), "cgsix tec");
-	all->par.thc = of_ioremap(&op->resource[0], CG6_THC_OFFSET,
+	par->thc = of_ioremap(&op->resource[0], CG6_THC_OFFSET,
 				  sizeof(struct cg6_thc), "cgsix thc");
-	all->par.bt = of_ioremap(&op->resource[0], CG6_BROOKTREE_OFFSET,
+	par->bt = of_ioremap(&op->resource[0], CG6_BROOKTREE_OFFSET,
 				 sizeof(struct bt_regs), "cgsix dac");
-	all->par.fhc = of_ioremap(&op->resource[0], CG6_FHC_OFFSET,
+	par->fhc = of_ioremap(&op->resource[0], CG6_FHC_OFFSET,
 				  sizeof(u32), "cgsix fhc");
 
-	all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_IMAGEBLIT |
+	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_IMAGEBLIT |
                           FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT;
-	all->info.fbops = &cg6_ops;
-
-	all->info.screen_base =  of_ioremap(&op->resource[0], CG6_RAM_OFFSET,
-					    all->par.fbsize, "cgsix ram");
-	if (!all->par.fbc || !all->par.tec || !all->par.thc ||
-	    !all->par.bt || !all->par.fhc || !all->info.screen_base) {
-		cg6_unmap_regs(op, all);
-		kfree(all);
-		return -ENOMEM;
-	}
+	info->fbops = &cg6_ops;
 
-	all->info.par = &all->par;
+	info->screen_base =  of_ioremap(&op->resource[0], CG6_RAM_OFFSET,
+					    par->fbsize, "cgsix ram");
+	if (!par->fbc || !par->tec || !par->thc ||
+	    !par->bt || !par->fhc || !info->screen_base)
+		goto out_unmap_regs;
 
-	all->info.var.accel_flags = FB_ACCELF_TEXT;
+	info->var.accel_flags = FB_ACCELF_TEXT;
 
-	cg6_bt_init(&all->par);
-	cg6_chip_init(&all->info);
-	cg6_blank(0, &all->info);
+	cg6_bt_init(par);
+	cg6_chip_init(info);
+	cg6_blank(0, info);
 
-	if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
-		cg6_unmap_regs(op, all);
-		kfree(all);
-		return -ENOMEM;
-	}
+	if (fb_alloc_cmap(&info->cmap, 256, 0))
+		goto out_unmap_regs;
 
-	fb_set_cmap(&all->info.cmap, &all->info);
-	cg6_init_fix(&all->info, linebytes);
+	fb_set_cmap(&info->cmap, info);
+	cg6_init_fix(info, linebytes);
 
-	err = register_framebuffer(&all->info);
-	if (err < 0) {
-		cg6_unmap_regs(op, all);
-		fb_dealloc_cmap(&all->info.cmap);
-		kfree(all);
-		return err;
-	}
+	err = register_framebuffer(info);
+	if (err < 0)
+		goto out_dealloc_cmap;
 
-	dev_set_drvdata(&op->dev, all);
+	dev_set_drvdata(&op->dev, info);
 
 	printk("%s: CGsix [%s] at %lx:%lx\n",
-	       dp->full_name,
-	       all->info.fix.id,
-	       all->par.which_io, all->par.physbase);
+	       dp->full_name, info->fix.id,
+	       par->which_io, par->physbase);
 
 	return 0;
-}
 
-static int __devinit cg6_probe(struct of_device *dev, const struct of_device_id *match)
-{
-	struct of_device *op = to_of_device(&dev->dev);
+out_dealloc_cmap:
+	fb_dealloc_cmap(&info->cmap);
+
+out_unmap_regs:
+	cg6_unmap_regs(op, info, par);
 
-	return cg6_init_one(op);
+out_err:
+	return err;
 }
 
 static int __devexit cg6_remove(struct of_device *op)
 {
-	struct all_info *all = dev_get_drvdata(&op->dev);
+	struct fb_info *info = dev_get_drvdata(&op->dev);
+	struct cg6_par *par = info->par;
 
-	unregister_framebuffer(&all->info);
-	fb_dealloc_cmap(&all->info.cmap);
+	unregister_framebuffer(info);
+	fb_dealloc_cmap(&info->cmap);
 
-	cg6_unmap_regs(op, all);
+	cg6_unmap_regs(op, info, par);
 
-	kfree(all);
+	framebuffer_release(info);
 
 	dev_set_drvdata(&op->dev, NULL);
 

+ 79 - 91
drivers/video/ffb.c

@@ -371,6 +371,8 @@ struct ffb_par {
 	unsigned long		fbsize;
 
 	int			board_type;
+
+	u32			pseudo_palette[16];
 };
 
 static void FFBFifo(struct ffb_par *par, int n)
@@ -900,75 +902,67 @@ ffb_init_fix(struct fb_info *info)
 	info->fix.accel = FB_ACCEL_SUN_CREATOR;
 }
 
-struct all_info {
-	struct fb_info info;
-	struct ffb_par par;
-	u32 pseudo_palette[16];
-};
-
-static int ffb_init_one(struct of_device *op)
+static int __devinit ffb_probe(struct of_device *op, const struct of_device_id *match)
 {
 	struct device_node *dp = op->node;
 	struct ffb_fbc __iomem *fbc;
 	struct ffb_dac __iomem *dac;
-	struct all_info *all;
-	int err;
+	struct fb_info *info;
+	struct ffb_par *par;
 	u32 dac_pnum, dac_rev, dac_mrev;
+	int err;
 
-	all = kzalloc(sizeof(*all), GFP_KERNEL);
-	if (!all)
-		return -ENOMEM;
+	info = framebuffer_alloc(sizeof(struct ffb_par), &op->dev);
 
-	spin_lock_init(&all->par.lock);
-	all->par.fbc = of_ioremap(&op->resource[2], 0,
-				  sizeof(struct ffb_fbc), "ffb fbc");
-	if (!all->par.fbc) {
-		kfree(all);
-		return -ENOMEM;
-	}
+	err = -ENOMEM;
+	if (!info)
+		goto out_err;
 
-	all->par.dac = of_ioremap(&op->resource[1], 0,
-				  sizeof(struct ffb_dac), "ffb dac");
-	if (!all->par.dac) {
-		of_iounmap(&op->resource[2],
-			   all->par.fbc, sizeof(struct ffb_fbc));
-		kfree(all);
-		return -ENOMEM;
-	}
+	par = info->par;
+
+	spin_lock_init(&par->lock);
+	par->fbc = of_ioremap(&op->resource[2], 0,
+			      sizeof(struct ffb_fbc), "ffb fbc");
+	if (!par->fbc)
+		goto out_release_fb;
+
+	par->dac = of_ioremap(&op->resource[1], 0,
+			      sizeof(struct ffb_dac), "ffb dac");
+	if (!par->dac)
+		goto out_unmap_fbc;
 
-	all->par.rop_cache = FFB_ROP_NEW;
-	all->par.physbase = op->resource[0].start;
+	par->rop_cache = FFB_ROP_NEW;
+	par->physbase = op->resource[0].start;
 
 	/* Don't mention copyarea, so SCROLL_REDRAW is always
 	 * used.  It is the fastest on this chip.
 	 */
-	all->info.flags = (FBINFO_DEFAULT |
-			   /* FBINFO_HWACCEL_COPYAREA | */
-			   FBINFO_HWACCEL_FILLRECT |
-			   FBINFO_HWACCEL_IMAGEBLIT);
-	all->info.fbops = &ffb_ops;
-	all->info.screen_base = (char *) all->par.physbase + FFB_DFB24_POFF;
-	all->info.par = &all->par;
-	all->info.pseudo_palette = all->pseudo_palette;
-
-	sbusfb_fill_var(&all->info.var, dp->node, 32);
-	all->par.fbsize = PAGE_ALIGN(all->info.var.xres *
-				     all->info.var.yres *
-				     4);
-	ffb_fixup_var_rgb(&all->info.var);
-
-	all->info.var.accel_flags = FB_ACCELF_TEXT;
+	info->flags = (FBINFO_DEFAULT |
+		       /* FBINFO_HWACCEL_COPYAREA | */
+		       FBINFO_HWACCEL_FILLRECT |
+		       FBINFO_HWACCEL_IMAGEBLIT);
+
+	info->fbops = &ffb_ops;
+
+	info->screen_base = (char *) par->physbase + FFB_DFB24_POFF;
+	info->pseudo_palette = par->pseudo_palette;
+
+	sbusfb_fill_var(&info->var, dp->node, 32);
+	par->fbsize = PAGE_ALIGN(info->var.xres * info->var.yres * 4);
+	ffb_fixup_var_rgb(&info->var);
+
+	info->var.accel_flags = FB_ACCELF_TEXT;
 
 	if (!strcmp(dp->name, "SUNW,afb"))
-		all->par.flags |= FFB_FLAG_AFB;
+		par->flags |= FFB_FLAG_AFB;
 
-	all->par.board_type = of_getintprop_default(dp, "board_type", 0);
+	par->board_type = of_getintprop_default(dp, "board_type", 0);
 
-	fbc = all->par.fbc;
+	fbc = par->fbc;
 	if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0)
 		upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr);
 
-	dac = all->par.dac;
+	dac = par->dac;
 	upa_writel(FFB_DAC_DID, &dac->type);
 	dac_pnum = upa_readl(&dac->value);
 	dac_rev = (dac_pnum & FFB_DAC_DID_REV) >> FFB_DAC_DID_REV_SHIFT;
@@ -985,76 +979,70 @@ static int ffb_init_one(struct of_device *op)
 	 * cursor logic.  We identify Pacifica 1 as not Pacifica 2, the
 	 * latter having a part number value of 0x236e.
 	 */
-	if ((all->par.flags & FFB_FLAG_AFB) || dac_pnum == 0x236e) {
-		all->par.flags &= ~FFB_FLAG_INVCURSOR;
+	if ((par->flags & FFB_FLAG_AFB) || dac_pnum == 0x236e) {
+		par->flags &= ~FFB_FLAG_INVCURSOR;
 	} else {
 		if (dac_mrev < 3)
-			all->par.flags |= FFB_FLAG_INVCURSOR;
+			par->flags |= FFB_FLAG_INVCURSOR;
 	}
 
-	ffb_switch_from_graph(&all->par);
+	ffb_switch_from_graph(par);
 
 	/* Unblank it just to be sure.  When there are multiple
 	 * FFB/AFB cards in the system, or it is not the OBP
 	 * chosen console, it will have video outputs off in
 	 * the DAC.
 	 */
-	ffb_blank(0, &all->info);
-
-	if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
-		printk(KERN_ERR "ffb: Could not allocate color map.\n");
-		of_iounmap(&op->resource[2],
-			   all->par.fbc, sizeof(struct ffb_fbc));
-		of_iounmap(&op->resource[1],
-			   all->par.dac, sizeof(struct ffb_dac));
-		kfree(all);
-		return -ENOMEM;
-	}
+	ffb_blank(0, info);
 
-	ffb_init_fix(&all->info);
-
-	err = register_framebuffer(&all->info);
-	if (err < 0) {
-		printk(KERN_ERR "ffb: Could not register framebuffer.\n");
-		fb_dealloc_cmap(&all->info.cmap);
-		of_iounmap(&op->resource[2],
-			   all->par.fbc, sizeof(struct ffb_fbc));
-		of_iounmap(&op->resource[1],
-			   all->par.dac, sizeof(struct ffb_dac));
-		kfree(all);
-		return err;
-	}
+	if (fb_alloc_cmap(&info->cmap, 256, 0))
+		goto out_unmap_dac;
+
+	ffb_init_fix(info);
 
-	dev_set_drvdata(&op->dev, all);
+	err = register_framebuffer(info);
+	if (err < 0)
+		goto out_dealloc_cmap;
+
+	dev_set_drvdata(&op->dev, info);
 
 	printk("%s: %s at %016lx, type %d, "
 	       "DAC pnum[%x] rev[%d] manuf_rev[%d]\n",
 	       dp->full_name,
-	       ((all->par.flags & FFB_FLAG_AFB) ? "AFB" : "FFB"),
-	       all->par.physbase, all->par.board_type,
+	       ((par->flags & FFB_FLAG_AFB) ? "AFB" : "FFB"),
+	       par->physbase, par->board_type,
 	       dac_pnum, dac_rev, dac_mrev);
 
 	return 0;
-}
 
-static int __devinit ffb_probe(struct of_device *dev, const struct of_device_id *match)
-{
-	struct of_device *op = to_of_device(&dev->dev);
+out_dealloc_cmap:
+	fb_dealloc_cmap(&info->cmap);
+
+out_unmap_dac:
+	of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc));
+
+out_unmap_fbc:
+	of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc));
+
+out_release_fb:
+	framebuffer_release(info);
 
-	return ffb_init_one(op);
+out_err:
+	return err;
 }
 
 static int __devexit ffb_remove(struct of_device *op)
 {
-	struct all_info *all = dev_get_drvdata(&op->dev);
+	struct fb_info *info = dev_get_drvdata(&op->dev);
+	struct ffb_par *par = info->par;
 
-	unregister_framebuffer(&all->info);
-	fb_dealloc_cmap(&all->info.cmap);
+	unregister_framebuffer(info);
+	fb_dealloc_cmap(&info->cmap);
 
-	of_iounmap(&op->resource[2], all->par.fbc, sizeof(struct ffb_fbc));
-	of_iounmap(&op->resource[1], all->par.dac, sizeof(struct ffb_dac));
+	of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc));
+	of_iounmap(&op->resource[1], par->dac, sizeof(struct ffb_dac));
 
-	kfree(all);
+	framebuffer_release(info);
 
 	dev_set_drvdata(&op->dev, NULL);
 

+ 70 - 77
drivers/video/leo.c

@@ -525,130 +525,123 @@ static void leo_fixup_var_rgb(struct fb_var_screeninfo *var)
 	var->transp.length = 0;
 }
 
-struct all_info {
-	struct fb_info info;
-	struct leo_par par;
-};
-
-static void leo_unmap_regs(struct of_device *op, struct all_info *all)
+static void leo_unmap_regs(struct of_device *op, struct fb_info *info,
+			   struct leo_par *par)
 {
-	if (all->par.lc_ss0_usr)
-		of_iounmap(&op->resource[0], all->par.lc_ss0_usr, 0x1000);
-	if (all->par.ld_ss0)
-		of_iounmap(&op->resource[0], all->par.ld_ss0, 0x1000);
-	if (all->par.ld_ss1)
-		of_iounmap(&op->resource[0], all->par.ld_ss1, 0x1000);
-	if (all->par.lx_krn)
-		of_iounmap(&op->resource[0], all->par.lx_krn, 0x1000);
-	if (all->par.cursor)
+	if (par->lc_ss0_usr)
+		of_iounmap(&op->resource[0], par->lc_ss0_usr, 0x1000);
+	if (par->ld_ss0)
+		of_iounmap(&op->resource[0], par->ld_ss0, 0x1000);
+	if (par->ld_ss1)
+		of_iounmap(&op->resource[0], par->ld_ss1, 0x1000);
+	if (par->lx_krn)
+		of_iounmap(&op->resource[0], par->lx_krn, 0x1000);
+	if (par->cursor)
 		of_iounmap(&op->resource[0],
-			   all->par.cursor, sizeof(struct leo_cursor));
-	if (all->info.screen_base)
-		of_iounmap(&op->resource[0], all->info.screen_base, 0x800000);
+			   par->cursor, sizeof(struct leo_cursor));
+	if (info->screen_base)
+		of_iounmap(&op->resource[0], info->screen_base, 0x800000);
 }
 
-static int __devinit leo_init_one(struct of_device *op)
+static int __devinit leo_probe(struct of_device *op, const struct of_device_id *match)
 {
 	struct device_node *dp = op->node;
-	struct all_info *all;
+	struct fb_info *info;
+	struct leo_par *par;
 	int linebytes, err;
 
-	all = kzalloc(sizeof(*all), GFP_KERNEL);
-	if (!all)
-		return -ENOMEM;
+	info = framebuffer_alloc(sizeof(struct leo_par), &op->dev);
+
+	err = -ENOMEM;
+	if (!info)
+		goto out_err;
+	par = info->par;
 
-	spin_lock_init(&all->par.lock);
+	spin_lock_init(&par->lock);
 
-	all->par.physbase = op->resource[0].start;
-	all->par.which_io = op->resource[0].flags & IORESOURCE_BITS;
+	par->physbase = op->resource[0].start;
+	par->which_io = op->resource[0].flags & IORESOURCE_BITS;
 
-	sbusfb_fill_var(&all->info.var, dp->node, 32);
-	leo_fixup_var_rgb(&all->info.var);
+	sbusfb_fill_var(&info->var, dp->node, 32);
+	leo_fixup_var_rgb(&info->var);
 
 	linebytes = of_getintprop_default(dp, "linebytes",
-					  all->info.var.xres);
-	all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
+					  info->var.xres);
+	par->fbsize = PAGE_ALIGN(linebytes * info->var.yres);
 
-	all->par.lc_ss0_usr =
+	par->lc_ss0_usr =
 		of_ioremap(&op->resource[0], LEO_OFF_LC_SS0_USR,
 			   0x1000, "leolc ss0usr");
-	all->par.ld_ss0 =
+	par->ld_ss0 =
 		of_ioremap(&op->resource[0], LEO_OFF_LD_SS0,
 			   0x1000, "leold ss0");
-	all->par.ld_ss1 =
+	par->ld_ss1 =
 		of_ioremap(&op->resource[0], LEO_OFF_LD_SS1,
 			   0x1000, "leold ss1");
-	all->par.lx_krn =
+	par->lx_krn =
 		of_ioremap(&op->resource[0], LEO_OFF_LX_KRN,
 			   0x1000, "leolx krn");
-	all->par.cursor =
+	par->cursor =
 		of_ioremap(&op->resource[0], LEO_OFF_LX_CURSOR,
 			   sizeof(struct leo_cursor), "leolx cursor");
-	all->info.screen_base = 
+	info->screen_base =
 		of_ioremap(&op->resource[0], LEO_OFF_SS0,
 			   0x800000, "leo ram");
-	if (!all->par.lc_ss0_usr ||
-	    !all->par.ld_ss0 ||
-	    !all->par.ld_ss1 ||
-	    !all->par.lx_krn ||
-	    !all->par.cursor ||
-	    !all->info.screen_base) {
-		leo_unmap_regs(op, all);
-		kfree(all);
-		return -ENOMEM;
-	}
+	if (!par->lc_ss0_usr ||
+	    !par->ld_ss0 ||
+	    !par->ld_ss1 ||
+	    !par->lx_krn ||
+	    !par->cursor ||
+	    !info->screen_base)
+		goto out_unmap_regs;
 
-	all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
-	all->info.fbops = &leo_ops;
-	all->info.par = &all->par;
+	info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
+	info->fbops = &leo_ops;
 
-	leo_init_wids(&all->info);
-	leo_init_hw(&all->info);
+	leo_init_wids(info);
+	leo_init_hw(info);
 
-	leo_blank(0, &all->info);
+	leo_blank(0, info);
 
-	if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
-		leo_unmap_regs(op, all);
-		kfree(all);
-		return -ENOMEM;;
-	}
+	if (fb_alloc_cmap(&info->cmap, 256, 0))
+		goto out_unmap_regs;
 
-	leo_init_fix(&all->info, dp);
+	leo_init_fix(info, dp);
 
-	err = register_framebuffer(&all->info);
-	if (err < 0) {
-		fb_dealloc_cmap(&all->info.cmap);
-		leo_unmap_regs(op, all);
-		kfree(all);
-		return err;
-	}
+	err = register_framebuffer(info);
+	if (err < 0)
+		goto out_dealloc_cmap;
 
-	dev_set_drvdata(&op->dev, all);
+	dev_set_drvdata(&op->dev, info);
 
 	printk("%s: leo at %lx:%lx\n",
 	       dp->full_name,
-	       all->par.which_io, all->par.physbase);
+	       par->which_io, par->physbase);
 
 	return 0;
-}
 
-static int __devinit leo_probe(struct of_device *dev, const struct of_device_id *match)
-{
-	struct of_device *op = to_of_device(&dev->dev);
+out_dealloc_cmap:
+	fb_dealloc_cmap(&info->cmap);
+
+out_unmap_regs:
+	leo_unmap_regs(op, info, par);
+	framebuffer_release(info);
 
-	return leo_init_one(op);
+out_err:
+	return err;
 }
 
 static int __devexit leo_remove(struct of_device *op)
 {
-	struct all_info *all = dev_get_drvdata(&op->dev);
+	struct fb_info *info = dev_get_drvdata(&op->dev);
+	struct leo_par *par = info->par;
 
-	unregister_framebuffer(&all->info);
-	fb_dealloc_cmap(&all->info.cmap);
+	unregister_framebuffer(info);
+	fb_dealloc_cmap(&info->cmap);
 
-	leo_unmap_regs(op, all);
+	leo_unmap_regs(op, info, par);
 
-	kfree(all);
+	framebuffer_release(info);
 
 	dev_set_drvdata(&op->dev, NULL);
 

+ 63 - 75
drivers/video/p9100.c

@@ -255,107 +255,95 @@ static void p9100_init_fix(struct fb_info *info, int linebytes, struct device_no
 	info->fix.accel = FB_ACCEL_SUN_CGTHREE;
 }
 
-struct all_info {
-	struct fb_info info;
-	struct p9100_par par;
-};
-
-static int __devinit p9100_init_one(struct of_device *op)
+static int __devinit p9100_probe(struct of_device *op, const struct of_device_id *match)
 {
 	struct device_node *dp = op->node;
-	struct all_info *all;
+	struct fb_info *info;
+	struct p9100_par *par;
 	int linebytes, err;
 
-	all = kzalloc(sizeof(*all), GFP_KERNEL);
-	if (!all)
-		return -ENOMEM;
+	info = framebuffer_alloc(sizeof(struct p9100_par), &op->dev);
+
+	err = -ENOMEM;
+	if (!info)
+		goto out_err;
+	par = info->par;
 
-	spin_lock_init(&all->par.lock);
+	spin_lock_init(&par->lock);
 
 	/* This is the framebuffer and the only resource apps can mmap.  */
-	all->par.physbase = op->resource[2].start;
-	all->par.which_io = op->resource[2].flags & IORESOURCE_BITS;
-
-	sbusfb_fill_var(&all->info.var, dp->node, 8);
-	all->info.var.red.length = 8;
-	all->info.var.green.length = 8;
-	all->info.var.blue.length = 8;
-
-	linebytes = of_getintprop_default(dp, "linebytes",
-					  all->info.var.xres);
-	all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
-
-	all->par.regs = of_ioremap(&op->resource[0], 0,
-				   sizeof(struct p9100_regs), "p9100 regs");
-	if (!all->par.regs) {
-		kfree(all);
-		return -ENOMEM;
-	}
+	par->physbase = op->resource[2].start;
+	par->which_io = op->resource[2].flags & IORESOURCE_BITS;
 
-	all->info.flags = FBINFO_DEFAULT;
-	all->info.fbops = &p9100_ops;
-	all->info.screen_base = of_ioremap(&op->resource[2], 0,
-					   all->par.fbsize, "p9100 ram");
-	if (!all->info.screen_base) {
-		of_iounmap(&op->resource[0],
-			   all->par.regs, sizeof(struct p9100_regs));
-		kfree(all);
-		return -ENOMEM;
-	}
-	all->info.par = &all->par;
+	sbusfb_fill_var(&info->var, dp->node, 8);
+	info->var.red.length = 8;
+	info->var.green.length = 8;
+	info->var.blue.length = 8;
 
-	p9100_blank(0, &all->info);
+	linebytes = of_getintprop_default(dp, "linebytes", info->var.xres);
+	par->fbsize = PAGE_ALIGN(linebytes * info->var.yres);
 
-	if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
-		of_iounmap(&op->resource[0],
-			   all->par.regs, sizeof(struct p9100_regs));
-		of_iounmap(&op->resource[2],
-			   all->info.screen_base, all->par.fbsize);
-		kfree(all);
-		return -ENOMEM;
-	}
+	par->regs = of_ioremap(&op->resource[0], 0,
+			       sizeof(struct p9100_regs), "p9100 regs");
+	if (!par->regs)
+		goto out_release_fb;
 
-	p9100_init_fix(&all->info, linebytes, dp);
-
-	err = register_framebuffer(&all->info);
-	if (err < 0) {
-		fb_dealloc_cmap(&all->info.cmap);
-		of_iounmap(&op->resource[0],
-			   all->par.regs, sizeof(struct p9100_regs));
-		of_iounmap(&op->resource[2],
-			   all->info.screen_base, all->par.fbsize);
-		kfree(all);
-		return err;
-	}
-	fb_set_cmap(&all->info.cmap, &all->info);
+	info->flags = FBINFO_DEFAULT;
+	info->fbops = &p9100_ops;
+	info->screen_base = of_ioremap(&op->resource[2], 0,
+				       par->fbsize, "p9100 ram");
+	if (!info->screen_base)
+		goto out_unmap_regs;
+
+	p9100_blank(0, info);
+
+	if (fb_alloc_cmap(&info->cmap, 256, 0))
+		goto out_unmap_screen;
 
-	dev_set_drvdata(&op->dev, all);
+	p9100_init_fix(info, linebytes, dp);
+
+	err = register_framebuffer(info);
+	if (err < 0)
+		goto out_dealloc_cmap;
+
+	fb_set_cmap(&info->cmap, info);
+
+	dev_set_drvdata(&op->dev, info);
 
 	printk("%s: p9100 at %lx:%lx\n",
 	       dp->full_name,
-	       all->par.which_io, all->par.physbase);
+	       par->which_io, par->physbase);
 
 	return 0;
-}
 
-static int __devinit p9100_probe(struct of_device *dev, const struct of_device_id *match)
-{
-	struct of_device *op = to_of_device(&dev->dev);
+out_dealloc_cmap:
+	fb_dealloc_cmap(&info->cmap);
+
+out_unmap_screen:
+	of_iounmap(&op->resource[2], info->screen_base, par->fbsize);
+
+out_unmap_regs:
+	of_iounmap(&op->resource[0], par->regs, sizeof(struct p9100_regs));
+
+out_release_fb:
+	framebuffer_release(info);
 
-	return p9100_init_one(op);
+out_err:
+	return err;
 }
 
 static int __devexit p9100_remove(struct of_device *op)
 {
-	struct all_info *all = dev_get_drvdata(&op->dev);
+	struct fb_info *info = dev_get_drvdata(&op->dev);
+	struct p9100_par *par = info->par;
 
-	unregister_framebuffer(&all->info);
-	fb_dealloc_cmap(&all->info.cmap);
+	unregister_framebuffer(info);
+	fb_dealloc_cmap(&info->cmap);
 
-	of_iounmap(&op->resource[0], all->par.regs, sizeof(struct p9100_regs));
-	of_iounmap(&op->resource[2], all->info.screen_base, all->par.fbsize);
+	of_iounmap(&op->resource[0], par->regs, sizeof(struct p9100_regs));
+	of_iounmap(&op->resource[2], info->screen_base, par->fbsize);
 
-	kfree(all);
+	framebuffer_release(info);
 
 	dev_set_drvdata(&op->dev, NULL);
 

+ 0 - 25
drivers/video/sbuslib.c

@@ -190,17 +190,6 @@ int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg,
 EXPORT_SYMBOL(sbusfb_ioctl_helper);
 
 #ifdef CONFIG_COMPAT
-struct  fbcmap32 {
-	int             index;          /* first element (0 origin) */
-	int             count;
-	u32		red;
-	u32		green;
-	u32		blue;
-};
-
-#define FBIOPUTCMAP32	_IOW('F', 3, struct fbcmap32)
-#define FBIOGETCMAP32	_IOW('F', 4, struct fbcmap32)
-
 static int fbiogetputcmap(struct fb_info *info, unsigned int cmd, unsigned long arg)
 {
 	struct fbcmap32 __user *argp = (void __user *)arg;
@@ -223,20 +212,6 @@ static int fbiogetputcmap(struct fb_info *info, unsigned int cmd, unsigned long
 			(unsigned long)p);
 }
 
-struct fbcursor32 {
-	short set;		/* what to set, choose from the list above */
-	short enable;		/* cursor on/off */
-	struct fbcurpos pos;	/* cursor position */
-	struct fbcurpos hot;	/* cursor hot spot */
-	struct fbcmap32 cmap;	/* color map info */
-	struct fbcurpos size;	/* cursor bit map size */
-	u32	image;		/* cursor image bits */
-	u32	mask;		/* cursor mask bits */
-};
-
-#define FBIOSCURSOR32	_IOW('F', 24, struct fbcursor32)
-#define FBIOGCURSOR32	_IOW('F', 25, struct fbcursor32)
-
 static int fbiogscursor(struct fb_info *info, unsigned long arg)
 {
 	struct fbcursor __user *p = compat_alloc_user_space(sizeof(*p));

+ 90 - 94
drivers/video/tcx.c

@@ -345,88 +345,82 @@ tcx_init_fix(struct fb_info *info, int linebytes)
 	info->fix.accel = FB_ACCEL_SUN_TCX;
 }
 
-struct all_info {
-	struct fb_info info;
-	struct tcx_par par;
-};
-
-static void tcx_unmap_regs(struct of_device *op, struct all_info *all)
+static void tcx_unmap_regs(struct of_device *op, struct fb_info *info,
+			   struct tcx_par *par)
 {
-	if (all->par.tec)
+	if (par->tec)
 		of_iounmap(&op->resource[7],
-			   all->par.tec, sizeof(struct tcx_tec));
-	if (all->par.thc)
+			   par->tec, sizeof(struct tcx_tec));
+	if (par->thc)
 		of_iounmap(&op->resource[9],
-			   all->par.thc, sizeof(struct tcx_thc));
-	if (all->par.bt)
+			   par->thc, sizeof(struct tcx_thc));
+	if (par->bt)
 		of_iounmap(&op->resource[8],
-			   all->par.bt, sizeof(struct bt_regs));
-	if (all->par.cplane)
+			   par->bt, sizeof(struct bt_regs));
+	if (par->cplane)
 		of_iounmap(&op->resource[4],
-			   all->par.cplane, all->par.fbsize * sizeof(u32));
-	if (all->info.screen_base)
+			   par->cplane, par->fbsize * sizeof(u32));
+	if (info->screen_base)
 		of_iounmap(&op->resource[0],
-			   all->info.screen_base, all->par.fbsize);
+			   info->screen_base, par->fbsize);
 }
 
 static int __devinit tcx_init_one(struct of_device *op)
 {
 	struct device_node *dp = op->node;
-	struct all_info *all;
+	struct fb_info *info;
+	struct tcx_par *par;
 	int linebytes, i, err;
 
-	all = kzalloc(sizeof(*all), GFP_KERNEL);
-	if (!all)
-		return -ENOMEM;
+	info = framebuffer_alloc(sizeof(struct tcx_par), &op->dev);
 
-	spin_lock_init(&all->par.lock);
+	err = -ENOMEM;
+	if (!info)
+		goto out_err;
+	par = info->par;
 
-	all->par.lowdepth =
+	spin_lock_init(&par->lock);
+
+	par->lowdepth =
 		(of_find_property(dp, "tcx-8-bit", NULL) != NULL);
 
-	sbusfb_fill_var(&all->info.var, dp->node, 8);
-	all->info.var.red.length = 8;
-	all->info.var.green.length = 8;
-	all->info.var.blue.length = 8;
+	sbusfb_fill_var(&info->var, dp->node, 8);
+	info->var.red.length = 8;
+	info->var.green.length = 8;
+	info->var.blue.length = 8;
 
 	linebytes = of_getintprop_default(dp, "linebytes",
-					  all->info.var.xres);
-	all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres);
+					  info->var.xres);
+	par->fbsize = PAGE_ALIGN(linebytes * info->var.yres);
 
-	all->par.tec = of_ioremap(&op->resource[7], 0,
+	par->tec = of_ioremap(&op->resource[7], 0,
 				  sizeof(struct tcx_tec), "tcx tec");
-	all->par.thc = of_ioremap(&op->resource[9], 0,
+	par->thc = of_ioremap(&op->resource[9], 0,
 				  sizeof(struct tcx_thc), "tcx thc");
-	all->par.bt = of_ioremap(&op->resource[8], 0,
+	par->bt = of_ioremap(&op->resource[8], 0,
 				 sizeof(struct bt_regs), "tcx dac");
-	all->info.screen_base = of_ioremap(&op->resource[0], 0,
-					   all->par.fbsize, "tcx ram");
-	if (!all->par.tec || !all->par.thc ||
-	    !all->par.bt || !all->info.screen_base) {
-		tcx_unmap_regs(op, all);
-		kfree(all);
-		return -ENOMEM;
-	}
-
-	memcpy(&all->par.mmap_map, &__tcx_mmap_map, sizeof(all->par.mmap_map));
-	if (!all->par.lowdepth) {
-		all->par.cplane = of_ioremap(&op->resource[4], 0,
-					     all->par.fbsize * sizeof(u32),
+	info->screen_base = of_ioremap(&op->resource[0], 0,
+					   par->fbsize, "tcx ram");
+	if (!par->tec || !par->thc ||
+	    !par->bt || !info->screen_base)
+		goto out_unmap_regs;
+
+	memcpy(&par->mmap_map, &__tcx_mmap_map, sizeof(par->mmap_map));
+	if (!par->lowdepth) {
+		par->cplane = of_ioremap(&op->resource[4], 0,
+					     par->fbsize * sizeof(u32),
 					     "tcx cplane");
-		if (!all->par.cplane) {
-			tcx_unmap_regs(op, all);
-			kfree(all);
-			return -ENOMEM;
-		}
+		if (!par->cplane)
+			goto out_unmap_regs;
 	} else {
-		all->par.mmap_map[1].size = SBUS_MMAP_EMPTY;
-		all->par.mmap_map[4].size = SBUS_MMAP_EMPTY;
-		all->par.mmap_map[5].size = SBUS_MMAP_EMPTY;
-		all->par.mmap_map[6].size = SBUS_MMAP_EMPTY;
+		par->mmap_map[1].size = SBUS_MMAP_EMPTY;
+		par->mmap_map[4].size = SBUS_MMAP_EMPTY;
+		par->mmap_map[5].size = SBUS_MMAP_EMPTY;
+		par->mmap_map[6].size = SBUS_MMAP_EMPTY;
 	}
 
-	all->par.physbase = 0;
-	all->par.which_io = op->resource[0].flags & IORESOURCE_BITS;
+	par->physbase = 0;
+	par->which_io = op->resource[0].flags & IORESOURCE_BITS;
 
 	for (i = 0; i < TCX_MMAP_ENTRIES; i++) {
 		int j;
@@ -444,53 +438,54 @@ static int __devinit tcx_init_one(struct of_device *op)
 			j = i;
 			break;
 		};
-		all->par.mmap_map[i].poff = op->resource[j].start;
+		par->mmap_map[i].poff = op->resource[j].start;
 	}
 
-	all->info.flags = FBINFO_DEFAULT;
-	all->info.fbops = &tcx_ops;
-	all->info.par = &all->par;
+	info->flags = FBINFO_DEFAULT;
+	info->fbops = &tcx_ops;
 
 	/* Initialize brooktree DAC. */
-	sbus_writel(0x04 << 24, &all->par.bt->addr);         /* color planes */
-	sbus_writel(0xff << 24, &all->par.bt->control);
-	sbus_writel(0x05 << 24, &all->par.bt->addr);
-	sbus_writel(0x00 << 24, &all->par.bt->control);
-	sbus_writel(0x06 << 24, &all->par.bt->addr);         /* overlay plane */
-	sbus_writel(0x73 << 24, &all->par.bt->control);
-	sbus_writel(0x07 << 24, &all->par.bt->addr);
-	sbus_writel(0x00 << 24, &all->par.bt->control);
-
-	tcx_reset(&all->info);
-
-	tcx_blank(FB_BLANK_UNBLANK, &all->info);
-
-	if (fb_alloc_cmap(&all->info.cmap, 256, 0)) {
-		tcx_unmap_regs(op, all);
-		kfree(all);
-		return -ENOMEM;
-	}
+	sbus_writel(0x04 << 24, &par->bt->addr);         /* color planes */
+	sbus_writel(0xff << 24, &par->bt->control);
+	sbus_writel(0x05 << 24, &par->bt->addr);
+	sbus_writel(0x00 << 24, &par->bt->control);
+	sbus_writel(0x06 << 24, &par->bt->addr);         /* overlay plane */
+	sbus_writel(0x73 << 24, &par->bt->control);
+	sbus_writel(0x07 << 24, &par->bt->addr);
+	sbus_writel(0x00 << 24, &par->bt->control);
+
+	tcx_reset(info);
 
-	fb_set_cmap(&all->info.cmap, &all->info);
-	tcx_init_fix(&all->info, linebytes);
+	tcx_blank(FB_BLANK_UNBLANK, info);
 
-	err = register_framebuffer(&all->info);
-	if (err < 0) {
-		fb_dealloc_cmap(&all->info.cmap);
-		tcx_unmap_regs(op, all);
-		kfree(all);
-		return err;
-	}
+	if (fb_alloc_cmap(&info->cmap, 256, 0))
+		goto out_unmap_regs;
+
+	fb_set_cmap(&info->cmap, info);
+	tcx_init_fix(info, linebytes);
+
+	err = register_framebuffer(info);
+	if (err < 0)
+		goto out_dealloc_cmap;
 
-	dev_set_drvdata(&op->dev, all);
+	dev_set_drvdata(&op->dev, info);
 
 	printk("%s: TCX at %lx:%lx, %s\n",
 	       dp->full_name,
-	       all->par.which_io,
+	       par->which_io,
 	       op->resource[0].start,
-	       all->par.lowdepth ? "8-bit only" : "24-bit depth");
+	       par->lowdepth ? "8-bit only" : "24-bit depth");
 
 	return 0;
+
+out_dealloc_cmap:
+	fb_dealloc_cmap(&info->cmap);
+
+out_unmap_regs:
+	tcx_unmap_regs(op, info, par);
+
+out_err:
+	return err;
 }
 
 static int __devinit tcx_probe(struct of_device *dev, const struct of_device_id *match)
@@ -502,14 +497,15 @@ static int __devinit tcx_probe(struct of_device *dev, const struct of_device_id
 
 static int __devexit tcx_remove(struct of_device *op)
 {
-	struct all_info *all = dev_get_drvdata(&op->dev);
+	struct fb_info *info = dev_get_drvdata(&op->dev);
+	struct tcx_par *par = info->par;
 
-	unregister_framebuffer(&all->info);
-	fb_dealloc_cmap(&all->info.cmap);
+	unregister_framebuffer(info);
+	fb_dealloc_cmap(&info->cmap);
 
-	tcx_unmap_regs(op, all);
+	tcx_unmap_regs(op, info, par);
 
-	kfree(all);
+	framebuffer_release(info);
 
 	dev_set_drvdata(&op->dev, NULL);
 

+ 20 - 0
fs/compat_ioctl.c

@@ -115,6 +115,10 @@
 #include <linux/dvb/video.h>
 #include <linux/lp.h>
 
+#ifdef CONFIG_SPARC
+#include <asm/fbio.h>
+#endif
+
 static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd,
 			      unsigned long arg, struct file *f)
 {
@@ -3493,6 +3497,22 @@ IGNORE_IOCTL(VFAT_IOCTL_READDIR_SHORT32)
 
 /* loop */
 IGNORE_IOCTL(LOOP_CLR_FD)
+
+#ifdef CONFIG_SPARC
+/* Sparc framebuffers, handled in sbusfb_compat_ioctl() */
+IGNORE_IOCTL(FBIOGTYPE)
+IGNORE_IOCTL(FBIOSATTR)
+IGNORE_IOCTL(FBIOGATTR)
+IGNORE_IOCTL(FBIOSVIDEO)
+IGNORE_IOCTL(FBIOGVIDEO)
+IGNORE_IOCTL(FBIOSCURPOS)
+IGNORE_IOCTL(FBIOGCURPOS)
+IGNORE_IOCTL(FBIOGCURMAX)
+IGNORE_IOCTL(FBIOPUTCMAP32)
+IGNORE_IOCTL(FBIOGETCMAP32)
+IGNORE_IOCTL(FBIOSCURSOR32)
+IGNORE_IOCTL(FBIOGCURSOR32)
+#endif
 };
 
 #define IOCTL_HASHSIZE 256

+ 4 - 1
fs/partitions/msdos.c

@@ -203,6 +203,7 @@ parse_solaris_x86(struct parsed_partitions *state, struct block_device *bdev,
 	Sector sect;
 	struct solaris_x86_vtoc *v;
 	int i;
+	short max_nparts;
 
 	v = (struct solaris_x86_vtoc *)read_dev_sector(bdev, offset+1, &sect);
 	if (!v)
@@ -218,7 +219,9 @@ parse_solaris_x86(struct parsed_partitions *state, struct block_device *bdev,
 		put_dev_sector(sect);
 		return;
 	}
-	for (i=0; i<SOLARIS_X86_NUMSLICE && state->next<state->limit; i++) {
+	/* Ensure we can handle previous case of VTOC with 8 entries gracefully */
+	max_nparts = le16_to_cpu (v->v_nparts) > 8 ? SOLARIS_X86_NUMSLICE : 8;
+	for (i=0; i<max_nparts && state->next<state->limit; i++) {
 		struct solaris_x86_slice *s = &v->v_slice[i];
 		if (s->s_size == 0)
 			continue;

+ 45 - 17
fs/partitions/sun.c

@@ -19,34 +19,47 @@ int sun_partition(struct parsed_partitions *state, struct block_device *bdev)
 	Sector sect;
 	struct sun_disklabel {
 		unsigned char info[128];   /* Informative text string */
-		unsigned char spare0[14];
-		struct sun_info {
-			unsigned char spare1;
-			unsigned char id;
-			unsigned char spare2;
-			unsigned char flags;
-		} infos[8];
-		unsigned char spare[246];  /* Boot information etc. */
+		struct sun_vtoc {
+		    __be32 version;     /* Layout version */
+		    char   volume[8];   /* Volume name */
+		    __be16 nparts;      /* Number of partitions */
+		    struct sun_info {           /* Partition hdrs, sec 2 */
+			__be16 id;
+			__be16 flags;
+		    } infos[8];
+		    __be16 padding;     /* Alignment padding */
+		    __be32 bootinfo[3];  /* Info needed by mboot */
+		    __be32 sanity;       /* To verify vtoc sanity */
+		    __be32 reserved[10]; /* Free space */
+		    __be32 timestamp[8]; /* Partition timestamp */
+		} vtoc;
+		__be32 write_reinstruct; /* sectors to skip, writes */
+		__be32 read_reinstruct;  /* sectors to skip, reads */
+		unsigned char spare[148]; /* Padding */
 		__be16 rspeed;     /* Disk rotational speed */
 		__be16 pcylcount;  /* Physical cylinder count */
 		__be16 sparecyl;   /* extra sects per cylinder */
-		unsigned char spare2[4];   /* More magic... */
+		__be16 obs1;       /* gap1 */
+		__be16 obs2;       /* gap2 */
 		__be16 ilfact;     /* Interleave factor */
 		__be16 ncyl;       /* Data cylinder count */
 		__be16 nacyl;      /* Alt. cylinder count */
 		__be16 ntrks;      /* Tracks per cylinder */
 		__be16 nsect;      /* Sectors per track */
-		unsigned char spare3[4];   /* Even more magic... */
+		__be16 obs3;       /* bhead - Label head offset */
+		__be16 obs4;       /* ppart - Physical Partition */
 		struct sun_partition {
 			__be32 start_cylinder;
 			__be32 num_sectors;
 		} partitions[8];
 		__be16 magic;      /* Magic number */
 		__be16 csum;       /* Label xor'd checksum */
-	} * label;		
+	} * label;
 	struct sun_partition *p;
 	unsigned long spc;
 	char b[BDEVNAME_SIZE];
+	int use_vtoc;
+	int nparts;
 
 	label = (struct sun_disklabel *)read_dev_sector(bdev, 0, &sect);
 	if (!label)
@@ -70,9 +83,22 @@ int sun_partition(struct parsed_partitions *state, struct block_device *bdev)
 		return 0;
 	}
 
-	/* All Sun disks have 8 partition entries */
+	/* Check to see if we can use the VTOC table */
+	use_vtoc = ((be32_to_cpu(label->vtoc.sanity) == SUN_VTOC_SANITY) &&
+		    (be32_to_cpu(label->vtoc.version) == 1) &&
+		    (be16_to_cpu(label->vtoc.nparts) <= 8));
+
+	/* Use 8 partition entries if not specified in validated VTOC */
+	nparts = (use_vtoc) ? be16_to_cpu(label->vtoc.nparts) : 8;
+
+	/*
+	 * So that old Linux-Sun partitions continue to work,
+	 * alow the VTOC to be used under the additional condition ...
+	 */
+	use_vtoc = use_vtoc || !(label->vtoc.sanity |
+				 label->vtoc.version | label->vtoc.nparts);
 	spc = be16_to_cpu(label->ntrks) * be16_to_cpu(label->nsect);
-	for (i = 0; i < 8; i++, p++) {
+	for (i = 0; i < nparts; i++, p++) {
 		unsigned long st_sector;
 		unsigned int num_sectors;
 
@@ -81,10 +107,12 @@ int sun_partition(struct parsed_partitions *state, struct block_device *bdev)
 		if (num_sectors) {
 			put_partition(state, slot, st_sector, num_sectors);
 			state->parts[slot].flags = 0;
-			if (label->infos[i].id == LINUX_RAID_PARTITION)
-				state->parts[slot].flags |= ADDPART_FLAG_RAID;
-			if (label->infos[i].id == SUN_WHOLE_DISK)
-				state->parts[slot].flags |= ADDPART_FLAG_WHOLEDISK;
+			if (use_vtoc) {
+				if (be16_to_cpu(label->vtoc.infos[i].id) == LINUX_RAID_PARTITION)
+					state->parts[slot].flags |= ADDPART_FLAG_RAID;
+				else if (be16_to_cpu(label->vtoc.infos[i].id) == SUN_WHOLE_DISK)
+					state->parts[slot].flags |= ADDPART_FLAG_WHOLEDISK;
+			}
 		}
 		slot++;
 	}

+ 1 - 0
fs/partitions/sun.h

@@ -3,5 +3,6 @@
  */
 
 #define SUN_LABEL_MAGIC          0xDABE
+#define SUN_VTOC_SANITY          0x600DDEEE
 
 int sun_partition(struct parsed_partitions *state, struct block_device *bdev);

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

@@ -10,6 +10,10 @@ 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;
 };

+ 50 - 30
include/asm-sparc/floppy.h

@@ -101,6 +101,29 @@ static struct sun_floppy_ops sun_fdops;
 #define CROSS_64KB(a,s) (0)
 
 /* Routines unique to each controller type on a Sun. */
+static void sun_set_dor(unsigned char value, int fdc_82077)
+{
+	if (sparc_cpu_model == sun4c) {
+		unsigned int bits = 0;
+		if (value & 0x10)
+			bits |= AUXIO_FLPY_DSEL;
+		if ((value & 0x80) == 0)
+			bits |= AUXIO_FLPY_EJCT;
+		set_auxio(bits, (~bits) & (AUXIO_FLPY_DSEL|AUXIO_FLPY_EJCT));
+	}
+	if (fdc_82077) {
+		sun_fdc->dor_82077 = value;
+	}
+}
+
+static unsigned char sun_read_dir(void)
+{
+	if (sparc_cpu_model == sun4c)
+		return (get_auxio() & AUXIO_FLPY_DCHG) ? 0x80 : 0;
+	else
+		return sun_fdc->dir_82077;
+}
+
 static unsigned char sun_82072_fd_inb(int port)
 {
 	udelay(5);
@@ -113,7 +136,7 @@ static unsigned char sun_82072_fd_inb(int port)
 	case 5: /* FD_DATA */
 		return sun_fdc->data_82072;
 	case 7: /* FD_DIR */
-		return (get_auxio() & AUXIO_FLPY_DCHG)? 0x80: 0;
+		return sun_read_dir();
 	};
 	panic("sun_82072_fd_inb: How did I get here?");
 }
@@ -126,20 +149,7 @@ static void sun_82072_fd_outb(unsigned char value, int port)
 		printk("floppy: Asked to write to unknown port %d\n", port);
 		panic("floppy: Port bolixed.");
 	case 2: /* FD_DOR */
-		/* Oh geese, 82072 on the Sun has no DOR register,
-		 * the functionality is implemented via the AUXIO
-		 * I/O register.  So we must emulate the behavior.
-		 *
-		 * ASSUMPTIONS:  There will only ever be one floppy
-		 *               drive attached to a Sun controller
-		 *               and it will be at drive zero.
-		 */
-		{
-			unsigned bits = 0;
-			if (value & 0x10) bits |= AUXIO_FLPY_DSEL;
-			if ((value & 0x80) == 0) bits |= AUXIO_FLPY_EJCT;
-			set_auxio(bits, (~bits) & (AUXIO_FLPY_DSEL|AUXIO_FLPY_EJCT));
-		}
+		sun_set_dor(value, 0);
 		break;
 	case 5: /* FD_DATA */
 		sun_fdc->data_82072 = value;
@@ -161,15 +171,22 @@ static unsigned char sun_82077_fd_inb(int port)
 	default:
 		printk("floppy: Asked to read unknown port %d\n", port);
 		panic("floppy: Port bolixed.");
+	case 0: /* FD_STATUS_0 */
+		return sun_fdc->status1_82077;
+	case 1: /* FD_STATUS_1 */
+		return sun_fdc->status2_82077;
+	case 2: /* FD_DOR */
+		return sun_fdc->dor_82077;
+	case 3: /* FD_TDR */
+		return sun_fdc->tapectl_82077;
 	case 4: /* FD_STATUS */
 		return sun_fdc->status_82077 & ~STATUS_DMA;
 	case 5: /* FD_DATA */
 		return sun_fdc->data_82077;
 	case 7: /* FD_DIR */
-		/* XXX: Is DCL on 0x80 in sun4m? */
-		return sun_fdc->dir_82077;
+		return sun_read_dir();
 	};
-	panic("sun_82072_fd_inb: How did I get here?");
+	panic("sun_82077_fd_inb: How did I get here?");
 }
 
 static void sun_82077_fd_outb(unsigned char value, int port)
@@ -180,8 +197,7 @@ static void sun_82077_fd_outb(unsigned char value, int port)
 		printk("floppy: Asked to write to unknown port %d\n", port);
 		panic("floppy: Port bolixed.");
 	case 2: /* FD_DOR */
-		/* Happily, the 82077 has a real DOR register. */
-		sun_fdc->dor_82077 = value;
+		sun_set_dor(value, 1);
 		break;
 	case 5: /* FD_DATA */
 		sun_fdc->data_82077 = value;
@@ -192,6 +208,9 @@ static void sun_82077_fd_outb(unsigned char value, int port)
 	case 4: /* FD_STATUS */
 		sun_fdc->status_82077 = value;
 		break;
+	case 3: /* FD_TDR */
+		sun_fdc->tapectl_82077 = value;
+		break;
 	};
 	return;
 }
@@ -332,16 +351,17 @@ static int sun_floppy_init(void)
 		goto no_sun_fdc;
 	}
 
-        if(sparc_cpu_model == sun4c) {
-                sun_fdops.fd_inb = sun_82072_fd_inb;
-                sun_fdops.fd_outb = sun_82072_fd_outb;
-                fdc_status = &sun_fdc->status_82072;
-                /* printk("AUXIO @0x%lx\n", auxio_register); */ /* P3 */
-        } else {
-                sun_fdops.fd_inb = sun_82077_fd_inb;
-                sun_fdops.fd_outb = sun_82077_fd_outb;
-                fdc_status = &sun_fdc->status_82077;
-                /* printk("DOR @0x%p\n", &sun_fdc->dor_82077); */ /* P3 */
+	sun_fdops.fd_inb = sun_82077_fd_inb;
+	sun_fdops.fd_outb = sun_82077_fd_outb;
+	fdc_status = &sun_fdc->status_82077;
+
+	if (sun_fdc->dor_82077 == 0x80) {
+		sun_fdc->dor_82077 = 0x02;
+		if (sun_fdc->dor_82077 == 0x80) {
+			sun_fdops.fd_inb = sun_82072_fd_inb;
+			sun_fdops.fd_outb = sun_82072_fd_outb;
+			fdc_status = &sun_fdc->status_82072;
+		}
 	}
 
 	/* Success... */

+ 82 - 255
include/asm-sparc64/dma-mapping.h

@@ -1,307 +1,134 @@
 #ifndef _ASM_SPARC64_DMA_MAPPING_H
 #define _ASM_SPARC64_DMA_MAPPING_H
 
-
-#ifdef CONFIG_PCI
-
-/* we implement the API below in terms of the existing PCI one,
- * so include it */
-#include <linux/pci.h>
-/* need struct page definitions */
+#include <linux/scatterlist.h>
 #include <linux/mm.h>
 
-#include <asm/of_device.h>
-
-static inline int
-dma_supported(struct device *dev, u64 mask)
-{
-	BUG_ON(dev->bus != &pci_bus_type);
-
-	return pci_dma_supported(to_pci_dev(dev), mask);
-}
-
-static inline int
-dma_set_mask(struct device *dev, u64 dma_mask)
-{
-	BUG_ON(dev->bus != &pci_bus_type);
-
-	return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
-}
-
-static inline void *
-dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
-		   gfp_t flag)
-{
-	BUG_ON(dev->bus != &pci_bus_type);
-
-	return pci_iommu_ops->alloc_consistent(to_pci_dev(dev), size, dma_handle, flag);
-}
-
-static inline void
-dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
-		    dma_addr_t dma_handle)
-{
-	BUG_ON(dev->bus != &pci_bus_type);
-
-	pci_free_consistent(to_pci_dev(dev), size, cpu_addr, dma_handle);
-}
-
-static inline dma_addr_t
-dma_map_single(struct device *dev, void *cpu_addr, size_t size,
-	       enum dma_data_direction direction)
-{
-	BUG_ON(dev->bus != &pci_bus_type);
-
-	return pci_map_single(to_pci_dev(dev), cpu_addr, size, (int)direction);
-}
-
-static inline void
-dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
-		 enum dma_data_direction direction)
-{
-	BUG_ON(dev->bus != &pci_bus_type);
-
-	pci_unmap_single(to_pci_dev(dev), dma_addr, size, (int)direction);
-}
-
-static inline dma_addr_t
-dma_map_page(struct device *dev, struct page *page,
-	     unsigned long offset, size_t size,
-	     enum dma_data_direction direction)
-{
-	BUG_ON(dev->bus != &pci_bus_type);
-
-	return pci_map_page(to_pci_dev(dev), page, offset, size, (int)direction);
-}
-
-static inline void
-dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
-	       enum dma_data_direction direction)
-{
-	BUG_ON(dev->bus != &pci_bus_type);
-
-	pci_unmap_page(to_pci_dev(dev), dma_address, size, (int)direction);
-}
-
-static inline int
-dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-	   enum dma_data_direction direction)
-{
-	BUG_ON(dev->bus != &pci_bus_type);
-
-	return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction);
-}
-
-static inline void
-dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
-	     enum dma_data_direction direction)
-{
-	BUG_ON(dev->bus != &pci_bus_type);
-
-	pci_unmap_sg(to_pci_dev(dev), sg, nhwentries, (int)direction);
-}
-
-static inline void
-dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
-			enum dma_data_direction direction)
-{
-	BUG_ON(dev->bus != &pci_bus_type);
-
-	pci_dma_sync_single_for_cpu(to_pci_dev(dev), dma_handle,
-				    size, (int)direction);
-}
-
-static inline void
-dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
-			   enum dma_data_direction direction)
-{
-	BUG_ON(dev->bus != &pci_bus_type);
-
-	pci_dma_sync_single_for_device(to_pci_dev(dev), dma_handle,
-				       size, (int)direction);
-}
-
-static inline void
-dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
-		    enum dma_data_direction direction)
-{
-	BUG_ON(dev->bus != &pci_bus_type);
-
-	pci_dma_sync_sg_for_cpu(to_pci_dev(dev), sg, nelems, (int)direction);
-}
-
-static inline void
-dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
-		       enum dma_data_direction direction)
-{
-	BUG_ON(dev->bus != &pci_bus_type);
-
-	pci_dma_sync_sg_for_device(to_pci_dev(dev), sg, nelems, (int)direction);
-}
-
-static inline int
-dma_mapping_error(dma_addr_t dma_addr)
-{
-	return pci_dma_mapping_error(dma_addr);
-}
-
-#else
-
-struct device;
-struct page;
-struct scatterlist;
-
-static inline int
-dma_supported(struct device *dev, u64 mask)
-{
-	BUG();
-	return 0;
-}
-
-static inline int
-dma_set_mask(struct device *dev, u64 dma_mask)
-{
-	BUG();
-	return 0;
-}
+#define DMA_ERROR_CODE	(~(dma_addr_t)0x0)
+
+struct dma_ops {
+	void *(*alloc_coherent)(struct device *dev, size_t size,
+				dma_addr_t *dma_handle, gfp_t flag);
+	void (*free_coherent)(struct device *dev, size_t size,
+			      void *cpu_addr, dma_addr_t dma_handle);
+	dma_addr_t (*map_single)(struct device *dev, void *cpu_addr,
+				 size_t size,
+				 enum dma_data_direction direction);
+	void (*unmap_single)(struct device *dev, dma_addr_t dma_addr,
+			     size_t size,
+			     enum dma_data_direction direction);
+	int (*map_sg)(struct device *dev, struct scatterlist *sg, int nents,
+		      enum dma_data_direction direction);
+	void (*unmap_sg)(struct device *dev, struct scatterlist *sg,
+			 int nhwentries,
+			 enum dma_data_direction direction);
+	void (*sync_single_for_cpu)(struct device *dev,
+				    dma_addr_t dma_handle, size_t size,
+				    enum dma_data_direction direction);
+	void (*sync_single_for_device)(struct device *dev,
+				       dma_addr_t dma_handle, size_t size,
+				       enum dma_data_direction direction);
+	void (*sync_sg_for_cpu)(struct device *dev, struct scatterlist *sg,
+				int nelems,
+				enum dma_data_direction direction);
+	void (*sync_sg_for_device)(struct device *dev, struct scatterlist *sg,
+				   int nelems,
+				   enum dma_data_direction direction);
+};
+extern const struct dma_ops *dma_ops;
+
+extern int dma_supported(struct device *dev, u64 mask);
+extern int dma_set_mask(struct device *dev, u64 dma_mask);
 
 static inline void *dma_alloc_coherent(struct device *dev, size_t size,
-			 dma_addr_t *dma_handle, gfp_t flag)
+				       dma_addr_t *dma_handle, gfp_t flag)
 {
-	BUG();
-	return NULL;
+	return dma_ops->alloc_coherent(dev, size, dma_handle, flag);
 }
 
 static inline void dma_free_coherent(struct device *dev, size_t size,
-		       void *vaddr, dma_addr_t dma_handle)
+				     void *cpu_addr, dma_addr_t dma_handle)
 {
-	BUG();
+	dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
 }
 
-static inline dma_addr_t
-dma_map_single(struct device *dev, void *cpu_addr, size_t size,
-	       enum dma_data_direction direction)
+static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
+					size_t size,
+					enum dma_data_direction direction)
 {
-	BUG();
-	return 0;
+	return dma_ops->map_single(dev, cpu_addr, size, direction);
 }
 
-static inline void
-dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
-		 enum dma_data_direction direction)
+static inline void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
+				    size_t size,
+				    enum dma_data_direction direction)
 {
-	BUG();
+	dma_ops->unmap_single(dev, dma_addr, size, direction);
 }
 
-static inline dma_addr_t
-dma_map_page(struct device *dev, struct page *page,
-	     unsigned long offset, size_t size,
-	     enum dma_data_direction direction)
+static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
+				      unsigned long offset, size_t size,
+				      enum dma_data_direction direction)
 {
-	BUG();
-	return 0;
+	return dma_ops->map_single(dev, page_address(page) + offset,
+				   size, direction);
 }
 
-static inline void
-dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
-	       enum dma_data_direction direction)
+static inline void dma_unmap_page(struct device *dev, dma_addr_t dma_address,
+				  size_t size,
+				  enum dma_data_direction direction)
 {
-	BUG();
+	dma_ops->unmap_single(dev, dma_address, size, direction);
 }
 
-static inline int
-dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-	   enum dma_data_direction direction)
+static inline int dma_map_sg(struct device *dev, struct scatterlist *sg,
+			     int nents, enum dma_data_direction direction)
 {
-	BUG();
-	return 0;
+	return dma_ops->map_sg(dev, sg, nents, direction);
 }
 
-static inline void
-dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
-	     enum dma_data_direction direction)
+static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
+				int nents, enum dma_data_direction direction)
 {
-	BUG();
+	dma_ops->unmap_sg(dev, sg, nents, direction);
 }
 
-static inline void
-dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
-			enum dma_data_direction direction)
+static inline void dma_sync_single_for_cpu(struct device *dev,
+					   dma_addr_t dma_handle, size_t size,
+					   enum dma_data_direction direction)
 {
-	BUG();
+	dma_ops->sync_single_for_cpu(dev, dma_handle, size, direction);
 }
 
-static inline void
-dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
-			   enum dma_data_direction direction)
+static inline void dma_sync_single_for_device(struct device *dev,
+					      dma_addr_t dma_handle,
+					      size_t size,
+					      enum dma_data_direction direction)
 {
-	BUG();
+	dma_ops->sync_single_for_device(dev, dma_handle, size, direction);
 }
 
-static inline void
-dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
-		    enum dma_data_direction direction)
+static inline void dma_sync_sg_for_cpu(struct device *dev,
+				       struct scatterlist *sg, int nelems,
+				       enum dma_data_direction direction)
 {
-	BUG();
+	dma_ops->sync_sg_for_cpu(dev, sg, nelems, direction);
 }
 
-static inline void
-dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
-		       enum dma_data_direction direction)
+static inline void dma_sync_sg_for_device(struct device *dev,
+					  struct scatterlist *sg, int nelems,
+					  enum dma_data_direction direction)
 {
-	BUG();
+	dma_ops->sync_sg_for_device(dev, sg, nelems, direction);
 }
 
-static inline int
-dma_mapping_error(dma_addr_t dma_addr)
+static inline int dma_mapping_error(dma_addr_t dma_addr)
 {
-	BUG();
-	return 0;
+	return (dma_addr == DMA_ERROR_CODE);
 }
 
-#endif /* PCI */
-
-
-/* Now for the API extensions over the pci_ one */
-
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
 #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
 #define dma_is_consistent(d, h)	(1)
 
-static inline int
-dma_get_cache_alignment(void)
-{
-	/* no easy way to get cache size on all processors, so return
-	 * the maximum possible, to be safe */
-	return (1 << INTERNODE_CACHE_SHIFT);
-}
-
-static inline void
-dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
-			      unsigned long offset, size_t size,
-			      enum dma_data_direction direction)
-{
-	/* just sync everything, that's all the pci API can do */
-	dma_sync_single_for_cpu(dev, dma_handle, offset+size, direction);
-}
-
-static inline void
-dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
-				 unsigned long offset, size_t size,
-				 enum dma_data_direction direction)
-{
-	/* just sync everything, that's all the pci API can do */
-	dma_sync_single_for_device(dev, dma_handle, offset+size, direction);
-}
-
-static inline void
-dma_cache_sync(struct device *dev, void *vaddr, size_t size,
-	       enum dma_data_direction direction)
-{
-	/* could define this in terms of the dma_cache ... operations,
-	 * but if you get this on a platform, you should convert the platform
-	 * to using the generic device DMA API */
-	BUG();
-}
-
 #endif /* _ASM_SPARC64_DMA_MAPPING_H */

+ 28 - 0
include/asm-sparc64/fbio.h

@@ -2,6 +2,7 @@
 #define __LINUX_FBIO_H
 
 #include <linux/compiler.h>
+#include <linux/types.h>
 
 /* Constants used for fbio SunOS compatibility */
 /* (C) 1996 Miguel de Icaza */
@@ -299,4 +300,31 @@ struct fb_clut32 {
 #define LEO_LD_GBL_MAP         0x01009000
 #define LEO_UNK2_MAP           0x0100a000
 
+#ifdef __KERNEL__
+struct  fbcmap32 {
+	int             index;          /* first element (0 origin) */
+	int             count;
+	u32		red;
+	u32		green;
+	u32		blue;
+};
+
+#define FBIOPUTCMAP32	_IOW('F', 3, struct fbcmap32)
+#define FBIOGETCMAP32	_IOW('F', 4, struct fbcmap32)
+
+struct fbcursor32 {
+	short set;		/* what to set, choose from the list above */
+	short enable;		/* cursor on/off */
+	struct fbcurpos pos;	/* cursor position */
+	struct fbcurpos hot;	/* cursor hot spot */
+	struct fbcmap32 cmap;	/* color map info */
+	struct fbcurpos size;	/* cursor bit map size */
+	u32	image;		/* cursor image bits */
+	u32	mask;		/* cursor mask bits */
+};
+
+#define FBIOSCURSOR32	_IOW('F', 24, struct fbcursor32)
+#define FBIOGCURSOR32	_IOW('F', 25, struct fbcursor32)
+#endif
+
 #endif /* __LINUX_FBIO_H */

+ 3 - 3
include/asm-sparc64/floppy.h

@@ -1,7 +1,6 @@
-/* $Id: floppy.h,v 1.32 2001/10/26 17:59:36 davem Exp $
- * asm-sparc64/floppy.h: Sparc specific parts of the Floppy driver.
+/* floppy.h: Sparc specific parts of the Floppy driver.
  *
- * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996, 2007 David S. Miller (davem@davemloft.net)
  * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  *
  * Ultra/PCI support added: Sep 1997  Eddie C. Dost  (ecd@skynet.be)
@@ -11,6 +10,7 @@
 #define __ASM_SPARC64_FLOPPY_H
 
 #include <linux/init.h>
+#include <linux/pci.h>
 
 #include <asm/page.h>
 #include <asm/pgtable.h>

+ 7 - 4
include/asm-sparc64/iommu.h

@@ -1,7 +1,6 @@
-/* $Id: iommu.h,v 1.10 2001/03/08 09:55:56 davem Exp $
- * iommu.h: Definitions for the sun5 IOMMU.
+/* iommu.h: Definitions for the sun5 IOMMU.
  *
- * Copyright (C) 1996, 1999 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1996, 1999, 2007 David S. Miller (davem@davemloft.net)
  */
 #ifndef _SPARC64_IOMMU_H
 #define _SPARC64_IOMMU_H
@@ -33,6 +32,7 @@ struct iommu {
 	unsigned long		iommu_tsbbase;
 	unsigned long		iommu_flush;
 	unsigned long		iommu_flushinv;
+	unsigned long		iommu_tags;
 	unsigned long		iommu_ctxflush;
 	unsigned long		write_complete_reg;
 	unsigned long		dummy_page;
@@ -54,4 +54,7 @@ struct strbuf {
 	volatile unsigned long	__flushflag_buf[(64+(64-1)) / sizeof(long)];
 };
 
-#endif /* !(_SPARC_IOMMU_H) */
+extern int iommu_table_init(struct iommu *iommu, int tsbsize,
+			    u32 dma_offset, u32 dma_addr_mask);
+
+#endif /* !(_SPARC64_IOMMU_H) */

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

@@ -117,7 +117,7 @@ static int __devinit ecpp_probe(struct of_device *op, const struct of_device_id
 	if (!strcmp(parent->name, "dma")) {
 		p = parport_pc_probe_port(base, base + 0x400,
 					  op->irqs[0], PARPORT_DMA_NOFIFO,
-					  op->dev.parent);
+					  op->dev.parent->parent);
 		if (!p)
 			return -ENOMEM;
 		dev_set_drvdata(&op->dev, p);

+ 42 - 110
include/asm-sparc64/pci.h

@@ -3,8 +3,7 @@
 
 #ifdef __KERNEL__
 
-#include <linux/fs.h>
-#include <linux/mm.h>
+#include <linux/dma-mapping.h>
 
 /* Can be used to override the logic in pci_scan_bus for skipping
  * already-configured bus numbers - to be used for buggy BIOSes
@@ -30,80 +29,42 @@ static inline void pcibios_penalize_isa_irq(int irq, int active)
 	/* We don't do dynamic PCI IRQ allocation */
 }
 
-/* Dynamic DMA mapping stuff.
- */
-
 /* The PCI address space does not equal the physical memory
  * address space.  The networking and block device layers use
  * this boolean for bounce buffer decisions.
  */
 #define PCI_DMA_BUS_IS_PHYS	(0)
 
-#include <asm/scatterlist.h>
-
-struct pci_dev;
-
-struct pci_iommu_ops {
-	void *(*alloc_consistent)(struct pci_dev *, size_t, dma_addr_t *, gfp_t);
-	void (*free_consistent)(struct pci_dev *, size_t, void *, dma_addr_t);
-	dma_addr_t (*map_single)(struct pci_dev *, void *, size_t, int);
-	void (*unmap_single)(struct pci_dev *, dma_addr_t, size_t, int);
-	int (*map_sg)(struct pci_dev *, struct scatterlist *, int, int);
-	void (*unmap_sg)(struct pci_dev *, struct scatterlist *, int, int);
-	void (*dma_sync_single_for_cpu)(struct pci_dev *, dma_addr_t, size_t, int);
-	void (*dma_sync_sg_for_cpu)(struct pci_dev *, struct scatterlist *, int, int);
-};
-
-extern const struct pci_iommu_ops *pci_iommu_ops;
-
-/* Allocate and map kernel buffer using consistent mode DMA for a device.
- * hwdev should be valid struct pci_dev pointer for PCI devices.
- */
-static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle)
+static inline void *pci_alloc_consistent(struct pci_dev *pdev, size_t size,
+					 dma_addr_t *dma_handle)
 {
-	return pci_iommu_ops->alloc_consistent(hwdev, size, dma_handle, GFP_ATOMIC);
+	return dma_alloc_coherent(&pdev->dev, size, dma_handle, GFP_ATOMIC);
 }
 
-/* Free and unmap a consistent DMA buffer.
- * cpu_addr is what was returned from pci_alloc_consistent,
- * size must be the same as what as passed into pci_alloc_consistent,
- * and likewise dma_addr must be the same as what *dma_addrp was set to.
- *
- * References to the memory and mappings associated with cpu_addr/dma_addr
- * past this call are illegal.
- */
-static inline void pci_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle)
+static inline void pci_free_consistent(struct pci_dev *pdev, size_t size,
+				       void *vaddr, dma_addr_t dma_handle)
 {
-	return pci_iommu_ops->free_consistent(hwdev, size, vaddr, dma_handle);
+	return dma_free_coherent(&pdev->dev, size, vaddr, dma_handle);
 }
 
-/* Map a single buffer of the indicated size for DMA in streaming mode.
- * The 32-bit bus address to use is returned.
- *
- * Once the device is given the dma address, the device owns this memory
- * until either pci_unmap_single or pci_dma_sync_single_for_cpu is performed.
- */
-static inline dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction)
+static inline dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr,
+					size_t size, int direction)
 {
-	return pci_iommu_ops->map_single(hwdev, ptr, size, direction);
+	return dma_map_single(&pdev->dev, ptr, size,
+			      (enum dma_data_direction) direction);
 }
 
-/* Unmap a single streaming mode DMA translation.  The dma_addr and size
- * must match what was provided for in a previous pci_map_single call.  All
- * other usages are undefined.
- *
- * After this call, reads by the cpu to the buffer are guaranteed to see
- * whatever the device wrote there.
- */
-static inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size, int direction)
+static inline void pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr,
+				    size_t size, int direction)
 {
-	pci_iommu_ops->unmap_single(hwdev, dma_addr, size, direction);
+	dma_unmap_single(&pdev->dev, dma_addr, size,
+			 (enum dma_data_direction) direction);
 }
 
-/* No highmem on sparc64, plus we have an IOMMU, so mapping pages is easy. */
 #define pci_map_page(dev, page, off, size, dir) \
 	pci_map_single(dev, (page_address(page) + (off)), size, dir)
-#define pci_unmap_page(dev,addr,sz,dir) pci_unmap_single(dev,addr,sz,dir)
+#define pci_unmap_page(dev,addr,sz,dir) \
+	pci_unmap_single(dev,addr,sz,dir)
 
 /* pci_unmap_{single,page} is not a nop, thus... */
 #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)	\
@@ -119,75 +80,48 @@ static inline void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr,
 #define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
 	(((PTR)->LEN_NAME) = (VAL))
 
-/* Map a set of buffers described by scatterlist in streaming
- * mode for DMA.  This is the scatter-gather version of the
- * above pci_map_single interface.  Here the scatter gather list
- * elements are each tagged with the appropriate dma address
- * and length.  They are obtained via sg_dma_{address,length}(SG).
- *
- * NOTE: An implementation may be able to use a smaller number of
- *       DMA address/length pairs than there are SG table elements.
- *       (for example via virtual mapping capabilities)
- *       The routine returns the number of addr/length pairs actually
- *       used, at most nents.
- *
- * Device ownership issues as mentioned above for pci_map_single are
- * the same here.
- */
-static inline int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction)
+static inline int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg,
+			     int nents, int direction)
 {
-	return pci_iommu_ops->map_sg(hwdev, sg, nents, direction);
+	return dma_map_sg(&pdev->dev, sg, nents,
+			  (enum dma_data_direction) direction);
 }
 
-/* Unmap a set of streaming mode DMA translations.
- * Again, cpu read rules concerning calls here are the same as for
- * pci_unmap_single() above.
- */
-static inline void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nhwents, int direction)
+static inline void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg,
+				int nents, int direction)
 {
-	pci_iommu_ops->unmap_sg(hwdev, sg, nhwents, direction);
+	dma_unmap_sg(&pdev->dev, sg, nents,
+		     (enum dma_data_direction) direction);
 }
 
-/* Make physical memory consistent for a single
- * streaming mode DMA translation after a transfer.
- *
- * If you perform a pci_map_single() but wish to interrogate the
- * buffer using the cpu, yet do not wish to teardown the PCI dma
- * mapping, you must call this function before doing so.  At the
- * next point you give the PCI dma address back to the card, you
- * must first perform a pci_dma_sync_for_device, and then the
- * device again owns the buffer.
- */
-static inline void pci_dma_sync_single_for_cpu(struct pci_dev *hwdev, dma_addr_t dma_handle, size_t size, int direction)
+static inline void pci_dma_sync_single_for_cpu(struct pci_dev *pdev,
+					       dma_addr_t dma_handle,
+					       size_t size, int direction)
 {
-	pci_iommu_ops->dma_sync_single_for_cpu(hwdev, dma_handle, size, direction);
+	dma_sync_single_for_cpu(&pdev->dev, dma_handle, size,
+				(enum dma_data_direction) direction);
 }
 
-static inline void
-pci_dma_sync_single_for_device(struct pci_dev *hwdev, dma_addr_t dma_handle,
-			       size_t size, int direction)
+static inline void pci_dma_sync_single_for_device(struct pci_dev *pdev,
+						  dma_addr_t dma_handle,
+						  size_t size, int direction)
 {
 	/* No flushing needed to sync cpu writes to the device.  */
-	BUG_ON(direction == PCI_DMA_NONE);
 }
 
-/* Make physical memory consistent for a set of streaming
- * mode DMA translations after a transfer.
- *
- * The same as pci_dma_sync_single_* but for a scatter-gather list,
- * same rules and usage.
- */
-static inline void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction)
+static inline void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev,
+					   struct scatterlist *sg,
+					   int nents, int direction)
 {
-	pci_iommu_ops->dma_sync_sg_for_cpu(hwdev, sg, nelems, direction);
+	dma_sync_sg_for_cpu(&pdev->dev, sg, nents,
+			    (enum dma_data_direction) direction);
 }
 
-static inline void
-pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sg,
-			int nelems, int direction)
+static inline void pci_dma_sync_sg_for_device(struct pci_dev *pdev,
+					      struct scatterlist *sg,
+					      int nelems, int direction)
 {
 	/* No flushing needed to sync cpu writes to the device.  */
-	BUG_ON(direction == PCI_DMA_NONE);
 }
 
 /* Return whether the given PCI device DMA address mask can
@@ -206,11 +140,9 @@ extern int pci_dma_supported(struct pci_dev *hwdev, u64 mask);
 #define PCI64_REQUIRED_MASK	(~(dma64_addr_t)0)
 #define PCI64_ADDR_BASE		0xfffc000000000000UL
 
-#define PCI_DMA_ERROR_CODE	(~(dma_addr_t)0x0)
-
 static inline int pci_dma_mapping_error(dma_addr_t dma_addr)
 {
-	return (dma_addr == PCI_DMA_ERROR_CODE);
+	return dma_mapping_error(dma_addr);
 }
 
 #ifdef CONFIG_PCI

+ 71 - 15
include/asm-sparc64/sbus.h

@@ -1,7 +1,6 @@
-/* $Id: sbus.h,v 1.14 2000/02/18 13:50:55 davem Exp $
- * sbus.h: Defines for the Sun SBus.
+/* sbus.h: Defines for the Sun SBus.
  *
- * Copyright (C) 1996, 1999 David S. Miller (davem@redhat.com)
+ * Copyright (C) 1996, 1999, 2007 David S. Miller (davem@davemloft.net)
  */
 
 #ifndef _SPARC64_SBUS_H
@@ -69,7 +68,6 @@ struct sbus_dev {
 /* This struct describes the SBus(s) found on this machine. */
 struct sbus_bus {
 	struct of_device	ofdev;
-	void			*iommu;		/* Opaque IOMMU cookie	*/
 	struct sbus_dev		*devices;	/* Tree of SBUS devices	*/
 	struct sbus_bus		*next;		/* Next SBUS in system	*/
 	int			prom_node;      /* OBP node of SBUS	*/
@@ -102,9 +100,18 @@ extern struct sbus_bus *sbus_root;
 extern void sbus_set_sbus64(struct sbus_dev *, int);
 extern void sbus_fill_device_irq(struct sbus_dev *);
 
-/* These yield IOMMU mappings in consistent mode. */
-extern void *sbus_alloc_consistent(struct sbus_dev *, size_t, dma_addr_t *dma_addrp);
-extern void sbus_free_consistent(struct sbus_dev *, size_t, void *, dma_addr_t);
+static inline void *sbus_alloc_consistent(struct sbus_dev *sdev , size_t size,
+					  dma_addr_t *dma_handle)
+{
+	return dma_alloc_coherent(&sdev->ofdev.dev, size,
+				  dma_handle, GFP_ATOMIC);
+}
+
+static inline void sbus_free_consistent(struct sbus_dev *sdev, size_t size,
+					void *vaddr, dma_addr_t dma_handle)
+{
+	return dma_free_coherent(&sdev->ofdev.dev, size, vaddr, dma_handle);
+}
 
 #define SBUS_DMA_BIDIRECTIONAL	DMA_BIDIRECTIONAL
 #define SBUS_DMA_TODEVICE	DMA_TO_DEVICE
@@ -112,18 +119,67 @@ extern void sbus_free_consistent(struct sbus_dev *, size_t, void *, dma_addr_t);
 #define	SBUS_DMA_NONE		DMA_NONE
 
 /* All the rest use streaming mode mappings. */
-extern dma_addr_t sbus_map_single(struct sbus_dev *, void *, size_t, int);
-extern void sbus_unmap_single(struct sbus_dev *, dma_addr_t, size_t, int);
-extern int sbus_map_sg(struct sbus_dev *, struct scatterlist *, int, int);
-extern void sbus_unmap_sg(struct sbus_dev *, struct scatterlist *, int, int);
+static inline dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr,
+					 size_t size, int direction)
+{
+	return dma_map_single(&sdev->ofdev.dev, ptr, size,
+			      (enum dma_data_direction) direction);
+}
+
+static inline void sbus_unmap_single(struct sbus_dev *sdev,
+				     dma_addr_t dma_addr, size_t size,
+				     int direction)
+{
+	dma_unmap_single(&sdev->ofdev.dev, dma_addr, size,
+			 (enum dma_data_direction) direction);
+}
+
+static inline int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg,
+			      int nents, int direction)
+{
+	return dma_map_sg(&sdev->ofdev.dev, sg, nents,
+			  (enum dma_data_direction) direction);
+}
+
+static inline void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg,
+				 int nents, int direction)
+{
+	dma_unmap_sg(&sdev->ofdev.dev, sg, nents,
+		     (enum dma_data_direction) direction);
+}
 
 /* Finally, allow explicit synchronization of streamable mappings. */
-extern void sbus_dma_sync_single_for_cpu(struct sbus_dev *, dma_addr_t, size_t, int);
+static inline void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev,
+						dma_addr_t dma_handle,
+						size_t size, int direction)
+{
+	dma_sync_single_for_cpu(&sdev->ofdev.dev, dma_handle, size,
+				(enum dma_data_direction) direction);
+}
 #define sbus_dma_sync_single sbus_dma_sync_single_for_cpu
-extern void sbus_dma_sync_single_for_device(struct sbus_dev *, dma_addr_t, size_t, int);
-extern void sbus_dma_sync_sg_for_cpu(struct sbus_dev *, struct scatterlist *, int, int);
+
+static inline void sbus_dma_sync_single_for_device(struct sbus_dev *sdev,
+						   dma_addr_t dma_handle,
+						   size_t size, int direction)
+{
+	/* No flushing needed to sync cpu writes to the device.  */
+}
+
+static inline void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev,
+					    struct scatterlist *sg,
+					    int nents, int direction)
+{
+	dma_sync_sg_for_cpu(&sdev->ofdev.dev, sg, nents,
+			    (enum dma_data_direction) direction);
+}
 #define sbus_dma_sync_sg sbus_dma_sync_sg_for_cpu
-extern void sbus_dma_sync_sg_for_device(struct sbus_dev *, struct scatterlist *, int, int);
+
+static inline void sbus_dma_sync_sg_for_device(struct sbus_dev *sdev,
+					       struct scatterlist *sg,
+					       int nents, int direction)
+{
+	/* No flushing needed to sync cpu writes to the device.  */
+}
 
 extern void sbus_arch_bus_ranges_init(struct device_node *, struct sbus_bus *);
 extern void sbus_setup_iommu(struct sbus_bus *, struct device_node *);

+ 1 - 1
include/linux/genhd.h

@@ -264,7 +264,7 @@ static inline void set_capacity(struct gendisk *disk, sector_t size)
 
 #ifdef CONFIG_SOLARIS_X86_PARTITION
 
-#define SOLARIS_X86_NUMSLICE	8
+#define SOLARIS_X86_NUMSLICE	16
 #define SOLARIS_X86_VTOC_SANE	(0x600DDEEEUL)
 
 struct solaris_x86_slice {