diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-30 11:06:55 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-30 11:06:55 -0700 |
commit | 9c837fb692b005203765d8a569a2fe43fdff9df1 (patch) | |
tree | 914146eb36c92c929bf32af69052e7d9fa28beb1 | |
parent | 63332a9d16e7dede26d252af3f9c4304b51e7974 (diff) | |
parent | c1f193a7aed1b468617bb26075777c0c2f4f597a (diff) |
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.
41 files changed, 1595 insertions, 2096 deletions
diff --git a/arch/sparc/defconfig b/arch/sparc/defconfig index fdc67238408..f7a50914919 100644 --- a/arch/sparc/defconfig +++ b/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,30 +607,10 @@ 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 # # CONFIG_RTC_CLASS is not set @@ -734,6 +629,11 @@ CONFIG_USB_ARCH_HAS_EHCI=y # # +# Userspace I/O +# +# CONFIG_UIO is not set + +# # Misc Linux/SPARC drivers # CONFIG_SUN_OPENPROMIO=m @@ -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 diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c index e3a537650db..39fbd3c8ab0 100644 --- a/arch/sparc/kernel/prom.c +++ b/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) { diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index b66876bf410..40d2f3aae91 100644 --- a/arch/sparc64/kernel/Makefile +++ b/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 diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index 6d2956179cd..bc9ae36f7a4 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/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; diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/iommu.c index 70d2364fdfe..b35a62167e9 100644 --- a/arch/sparc64/kernel/pci_iommu.c +++ b/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); diff --git a/arch/sparc64/kernel/isa.c b/arch/sparc64/kernel/isa.c index 1a1043fcf97..0f19dce1c90 100644 --- a/arch/sparc64/kernel/isa.c +++ b/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; diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 55ad1b899bb..3d93e9203ba 100644 --- a/arch/sparc64/kernel/pci.c +++ b/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) */ diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c index 4249214608a..2f61c4b1259 100644 --- a/arch/sparc64/kernel/pci_common.c +++ b/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; diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index 7f5d473901c..14d67fe21ab 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/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: diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index 598393a2df1..b6b4cfea5b5 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/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(); } diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index 22e1be5c748..fba67c3d880 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/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(); } diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index ae76898bbe2..3c30bfa1f3a 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/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(); } diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 639cf06ca37..466f4aa8fc8 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/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); diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index a1fd9bcc0b8..d1fb13ba02b 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/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) diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 49063ca2efc..69cad1b653c 100644 --- a/arch/sparc64/kernel/time.c +++ b/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; diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index 6ef2d299fb1..6ef42b8e53d 100644 --- a/arch/sparc64/kernel/traps.c +++ b/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); diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index 17123e9ecf7..9f7740eee8d 100644 --- a/arch/sparc64/mm/fault.c +++ b/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); } diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c index 2553629ec15..c37d7c2587f 100644 --- a/drivers/sbus/sbus.c +++ b/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); diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c index b0b2e40bbd9..718b9f83736 100644 --- a/drivers/video/bw2.c +++ b/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); diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c index b071bb632b9..41f6dbf61be 100644 --- a/drivers/video/cg14.c +++ b/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); diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c index f042428a84f..5741b46ade1 100644 --- a/drivers/video/cg3.c +++ b/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); diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c index 4dad23a28f5..87c74712353 100644 --- a/drivers/video/cg6.c +++ b/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); diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c index 3f6c98fad43..4b520b57391 100644 --- a/drivers/video/ffb.c +++ b/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); diff --git a/drivers/video/leo.c b/drivers/video/leo.c index a038aa5a9e1..45b9a5d55de 100644 --- a/drivers/video/leo.c +++ b/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); diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c index 637b78bb4bf..58496061142 100644 --- a/drivers/video/p9100.c +++ b/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); diff --git a/drivers/video/sbuslib.c b/drivers/video/sbuslib.c index 34ef859ee41..963a454b707 100644 --- a/drivers/video/sbuslib.c +++ b/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)); diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c index 5a99669232c..e5a9ddb3c8b 100644 --- a/drivers/video/tcx.c +++ b/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); diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index e440a7b95d0..2bc1428d621 100644 --- a/fs/compat_ioctl.c +++ b/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 diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c index 4ccec4cd136..5567ec0d03a 100644 --- a/fs/partitions/msdos.c +++ b/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, §); 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; diff --git a/fs/partitions/sun.c b/fs/partitions/sun.c index 123f8b46c8b..794118da4ef 100644 --- a/fs/partitions/sun.c +++ b/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, §); 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++; } diff --git a/fs/partitions/sun.h b/fs/partitions/sun.h index b1b19fda7b2..7f864d1f86d 100644 --- a/fs/partitions/sun.h +++ b/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); diff --git a/include/asm-sparc/device.h b/include/asm-sparc/device.h index 4a56d84d69c..c0a7786d65f 100644 --- a/include/asm-sparc/device.h +++ b/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; }; diff --git a/include/asm-sparc/floppy.h b/include/asm-sparc/floppy.h index 9073c84218c..28ce2b9c3da 100644 --- a/include/asm-sparc/floppy.h +++ b/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... */ diff --git a/include/asm-sparc64/dma-mapping.h b/include/asm-sparc64/dma-mapping.h index c58ec1661df..0a1006692bb 100644 --- a/include/asm-sparc64/dma-mapping.h +++ b/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 */ diff --git a/include/asm-sparc64/fbio.h b/include/asm-sparc64/fbio.h index 500026d9f6e..b9215a0907d 100644 --- a/include/asm-sparc64/fbio.h +++ b/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 */ diff --git a/include/asm-sparc64/floppy.h b/include/asm-sparc64/floppy.h index 4aa0925e1b1..1783239c7b4 100644 --- a/include/asm-sparc64/floppy.h +++ b/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> diff --git a/include/asm-sparc64/iommu.h b/include/asm-sparc64/iommu.h index 0b1813f4104..9eac6676caf 100644 --- a/include/asm-sparc64/iommu.h +++ b/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) */ diff --git a/include/asm-sparc64/parport.h b/include/asm-sparc64/parport.h index 600afe5ae2e..8116e8f6062 100644 --- a/include/asm-sparc64/parport.h +++ b/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); diff --git a/include/asm-sparc64/pci.h b/include/asm-sparc64/pci.h index e11ac100f04..1393e57d50f 100644 --- a/include/asm-sparc64/pci.h +++ b/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 diff --git a/include/asm-sparc64/sbus.h b/include/asm-sparc64/sbus.h index 7efd49d31bb..0151cad486f 100644 --- a/include/asm-sparc64/sbus.h +++ b/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 *); diff --git a/include/linux/genhd.h b/include/linux/genhd.h index 9756fc102a8..a47b8025d39 100644 --- a/include/linux/genhd.h +++ b/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 { |