From d2d83475204be61d624153d8aaa15b3c013e428c Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 12 Oct 2007 10:19:26 +0300 Subject: [PATCH] --- yaml --- r: 68639 b: refs/heads/master c: 34627f0e768de6af95e3523c29a16cbb95ce3197 h: refs/heads/master i: 68637: 173930a90882942a6c0bb5fe4bb27b37247dc5f3 68635: 975c7189957a327614b54569bd2512b2b4589204 68631: f1024d00f50e9348f6c3848745e5402aa3f17143 68623: 9a813082fc1dee16f6d93ec6340defe21de15e29 68607: 55b50b910eceaa64163a1eade6d44ed3fb21e653 v: v3 --- [refs] | 2 +- trunk/Documentation/sparc/sbus_drivers.txt | 4 +- trunk/arch/powerpc/platforms/52xx/lite5200.c | 12 + trunk/arch/sparc/Kconfig.debug | 4 - trunk/arch/sparc/kernel/irq.c | 12 +- trunk/arch/sparc/kernel/of_device.c | 5 +- trunk/arch/sparc/kernel/time.c | 4 +- trunk/arch/sparc/kernel/vmlinux.lds.S | 165 +++-- trunk/arch/sparc64/defconfig | 38 +- trunk/arch/sparc64/kernel/Makefile | 1 - trunk/arch/sparc64/kernel/auxio.c | 4 +- trunk/arch/sparc64/kernel/entry.S | 14 +- trunk/arch/sparc64/kernel/irq.c | 610 +++++++++++-------- trunk/arch/sparc64/kernel/of_device.c | 5 +- trunk/arch/sparc64/kernel/pci.c | 60 +- trunk/arch/sparc64/kernel/pci_fire.c | 279 +-------- trunk/arch/sparc64/kernel/pci_impl.h | 32 +- trunk/arch/sparc64/kernel/pci_msi.c | 433 ------------- trunk/arch/sparc64/kernel/pci_psycho.c | 6 + trunk/arch/sparc64/kernel/pci_schizo.c | 3 + trunk/arch/sparc64/kernel/pci_sun4v.c | 405 ++++++++---- trunk/arch/sparc64/kernel/power.c | 4 +- trunk/arch/sparc64/kernel/sun4v_ivec.S | 22 +- trunk/arch/sparc64/kernel/sys_sparc.c | 15 +- trunk/arch/sparc64/kernel/time.c | 4 +- trunk/arch/sparc64/kernel/traps.c | 4 +- trunk/arch/sparc64/kernel/vmlinux.lds.S | 211 +++---- trunk/arch/sparc64/lib/xor.S | 12 +- trunk/arch/sparc64/mm/init.c | 2 + trunk/drivers/ata/pata_mpc52xx.c | 1 + trunk/drivers/base/memory.c | 2 +- trunk/drivers/mmc/core/sdio_bus.c | 15 +- trunk/drivers/mtd/onenand/onenand_base.c | 18 +- trunk/drivers/net/ibm_newemac/rgmii.c | 2 +- trunk/drivers/serial/mpc52xx_uart.c | 8 +- trunk/drivers/ssb/main.c | 10 +- trunk/drivers/ssb/pcmcia.c | 1 - trunk/drivers/usb/host/ohci-ssb.c | 2 - trunk/drivers/video/cg6.c | 294 ++++----- trunk/drivers/video/ffb.c | 161 ++--- trunk/drivers/video/xilinxfb.c | 2 +- trunk/include/asm-sparc/irqflags.h | 39 -- trunk/include/asm-sparc/system.h | 22 +- trunk/include/asm-sparc64/cpudata.h | 21 +- trunk/include/asm-sparc64/irq.h | 13 +- 45 files changed, 1202 insertions(+), 1781 deletions(-) delete mode 100644 trunk/arch/sparc64/kernel/pci_msi.c delete mode 100644 trunk/include/asm-sparc/irqflags.h diff --git a/[refs] b/[refs] index 425b28092153..2d92e8ed55d5 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: cbe619b162121577bc1e8ed4384dfb85f19e43d8 +refs/heads/master: 34627f0e768de6af95e3523c29a16cbb95ce3197 diff --git a/trunk/Documentation/sparc/sbus_drivers.txt b/trunk/Documentation/sparc/sbus_drivers.txt index eb1e28ad8822..8418d35484fc 100644 --- a/trunk/Documentation/sparc/sbus_drivers.txt +++ b/trunk/Documentation/sparc/sbus_drivers.txt @@ -67,12 +67,10 @@ probe in an SBUS driver under Linux: MODULE_DEVICE_TABLE(of, mydevice_match); static struct of_platform_driver mydevice_driver = { + .name = "mydevice", .match_table = mydevice_match, .probe = mydevice_probe, .remove = __devexit_p(mydevice_remove), - .driver = { - .name = "mydevice", - }, }; static int __init mydevice_init(void) diff --git a/trunk/arch/powerpc/platforms/52xx/lite5200.c b/trunk/arch/powerpc/platforms/52xx/lite5200.c index 65b7ae426238..774f2493e1ef 100644 --- a/trunk/arch/powerpc/platforms/52xx/lite5200.c +++ b/trunk/arch/powerpc/platforms/52xx/lite5200.c @@ -158,6 +158,18 @@ static void __init lite5200_setup_arch(void) of_node_put(np); } #endif + +#ifdef CONFIG_BLK_DEV_INITRD + if (initrd_start) + ROOT_DEV = Root_RAM0; + else +#endif +#ifdef CONFIG_ROOT_NFS + ROOT_DEV = Root_NFS; +#else + ROOT_DEV = Root_HDA1; +#endif + } /* diff --git a/trunk/arch/sparc/Kconfig.debug b/trunk/arch/sparc/Kconfig.debug index 87dd496f15eb..120f6b529348 100644 --- a/trunk/arch/sparc/Kconfig.debug +++ b/trunk/arch/sparc/Kconfig.debug @@ -1,9 +1,5 @@ menu "Kernel hacking" -config TRACE_IRQFLAGS_SUPPORT - bool - default y - source "lib/Kconfig.debug" config DEBUG_STACK_USAGE diff --git a/trunk/arch/sparc/kernel/irq.c b/trunk/arch/sparc/kernel/irq.c index 722d67d32961..b76dc03fc318 100644 --- a/trunk/arch/sparc/kernel/irq.c +++ b/trunk/arch/sparc/kernel/irq.c @@ -56,7 +56,7 @@ #define SMP_NOP2 #define SMP_NOP3 #endif /* SMP */ -unsigned long __raw_local_irq_save(void) +unsigned long __local_irq_save(void) { unsigned long retval; unsigned long tmp; @@ -74,7 +74,7 @@ unsigned long __raw_local_irq_save(void) return retval; } -void raw_local_irq_enable(void) +void local_irq_enable(void) { unsigned long tmp; @@ -89,7 +89,7 @@ void raw_local_irq_enable(void) : "memory"); } -void raw_local_irq_restore(unsigned long old_psr) +void local_irq_restore(unsigned long old_psr) { unsigned long tmp; @@ -105,9 +105,9 @@ void raw_local_irq_restore(unsigned long old_psr) : "memory"); } -EXPORT_SYMBOL(__raw_local_irq_save); -EXPORT_SYMBOL(raw_local_irq_enable); -EXPORT_SYMBOL(raw_local_irq_restore); +EXPORT_SYMBOL(__local_irq_save); +EXPORT_SYMBOL(local_irq_enable); +EXPORT_SYMBOL(local_irq_restore); /* * Dave Redman (djhr@tadpole.co.uk) diff --git a/trunk/arch/sparc/kernel/of_device.c b/trunk/arch/sparc/kernel/of_device.c index fb2caef79cec..36383f73d685 100644 --- a/trunk/arch/sparc/kernel/of_device.c +++ b/trunk/arch/sparc/kernel/of_device.c @@ -588,10 +588,7 @@ __setup("of_debug=", of_debug); int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus) { /* initialize common driver fields */ - if (!drv->driver.name) - drv->driver.name = drv->name; - if (!drv->driver.owner) - drv->driver.owner = drv->owner; + drv->driver.name = drv->name; drv->driver.bus = bus; /* register with core */ diff --git a/trunk/arch/sparc/kernel/time.c b/trunk/arch/sparc/kernel/time.c index 4bf78a5e8e0f..6a2513321620 100644 --- a/trunk/arch/sparc/kernel/time.c +++ b/trunk/arch/sparc/kernel/time.c @@ -347,11 +347,9 @@ static struct of_device_id clock_match[] = { }; static struct of_platform_driver clock_driver = { + .name = "clock", .match_table = clock_match, .probe = clock_probe, - .driver = { - .name = "clock", - }, }; diff --git a/trunk/arch/sparc/kernel/vmlinux.lds.S b/trunk/arch/sparc/kernel/vmlinux.lds.S index a8b4200f9cc3..15109c156e83 100644 --- a/trunk/arch/sparc/kernel/vmlinux.lds.S +++ b/trunk/arch/sparc/kernel/vmlinux.lds.S @@ -1,7 +1,6 @@ /* ld script to make SparcLinux kernel */ #include -#include OUTPUT_FORMAT("elf32-sparc", "elf32-sparc", "elf32-sparc") OUTPUT_ARCH(sparc) @@ -9,104 +8,84 @@ ENTRY(_start) jiffies = jiffies_64 + 4; SECTIONS { - . = 0x10000 + SIZEOF_HEADERS; - .text 0xf0004000 : - { - _text = .; - TEXT_TEXT - SCHED_TEXT - LOCK_TEXT - *(.gnu.warning) - } = 0 - _etext = .; - PROVIDE (etext = .); - RODATA - .data : { - DATA_DATA - CONSTRUCTORS - } - .data1 : { - *(.data1) - } - _edata = .; - PROVIDE (edata = .); + . = 0x10000 + SIZEOF_HEADERS; + .text 0xf0004000 : + { + _text = .; + TEXT_TEXT + SCHED_TEXT + LOCK_TEXT + *(.gnu.warning) + } =0 + _etext = .; + PROVIDE (etext = .); + RODATA + .data : + { + DATA_DATA + CONSTRUCTORS + } + .data1 : { *(.data1) } + _edata = .; + PROVIDE (edata = .); + __start___fixup = .; + .fixup : { *(.fixup) } + __stop___fixup = .; + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; - .fixup : { - __start___fixup = .; - *(.fixup) - __stop___fixup = .; - } - __ex_table : { - __start___ex_table = .; - *(__ex_table) - __stop___ex_table = .; - } + NOTES - NOTES - - . = ALIGN(PAGE_SIZE); - __init_begin = .; - .init.text : { - _sinittext = .; - *(.init.text) - _einittext = .; - } - __init_text_end = .; - .init.data : { - *(.init.data) - } - . = ALIGN(16); - .init.setup : { - __setup_start = .; - *(.init.setup) - __setup_end = .; - } - .initcall.init : { - __initcall_start = .; - INITCALLS - __initcall_end = .; - } - .con_initcall.init : { - __con_initcall_start = .; - *(.con_initcall.init) - __con_initcall_end = .; - } - SECURITY_INIT + . = ALIGN(4096); + __init_begin = .; + _sinittext = .; + .init.text : { + *(.init.text) + } + _einittext = .; + __init_text_end = .; + .init.data : { *(.init.data) } + . = ALIGN(16); + __setup_start = .; + .init.setup : { *(.init.setup) } + __setup_end = .; + __initcall_start = .; + .initcall.init : { + INITCALLS + } + __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; + SECURITY_INIT #ifdef CONFIG_BLK_DEV_INITRD - . = ALIGN(PAGE_SIZE); - .init.ramfs : { - __initramfs_start = .; - *(.init.ramfs) - __initramfs_end = .; - } + . = ALIGN(4096); + __initramfs_start = .; + .init.ramfs : { *(.init.ramfs) } + __initramfs_end = .; #endif - PERCPU(PAGE_SIZE) - . = ALIGN(PAGE_SIZE); - __init_end = .; - . = ALIGN(32); - .data.cacheline_aligned : { - *(.data.cacheline_aligned) - } + PERCPU(4096) + . = ALIGN(4096); + __init_end = .; + . = ALIGN(32); + .data.cacheline_aligned : { *(.data.cacheline_aligned) } + + __bss_start = .; + .sbss : { *(.sbss) *(.scommon) } + .bss : + { + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); + /DISCARD/ : { *(.exit.text) *(.exit.data) *(.exitcall.exit) } - __bss_start = .; - .sbss : { - *(.sbss) - *(.scommon) } - .bss : { - *(.dynbss) - *(.bss) - *(COMMON) - } - _end = . ; - PROVIDE (end = .); - /DISCARD/ : { - *(.exit.text) - *(.exit.data) - *(.exitcall.exit) - } + STABS_DEBUG - STABS_DEBUG - DWARF_DEBUG + DWARF_DEBUG } diff --git a/trunk/arch/sparc64/defconfig b/trunk/arch/sparc64/defconfig index 1aa2c4048e4b..7d07297db878 100644 --- a/trunk/arch/sparc64/defconfig +++ b/trunk/arch/sparc64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.23 -# Sat Oct 13 21:53:54 2007 +# Linux kernel version: 2.6.23-rc6 +# Sun Sep 16 09:52:11 2007 # CONFIG_SPARC=y CONFIG_SPARC64=y @@ -69,6 +69,7 @@ CONFIG_FUTEX=y CONFIG_ANON_INODES=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_VM_EVENT_COUNTERS=y @@ -88,7 +89,6 @@ CONFIG_KMOD=y CONFIG_BLOCK=y CONFIG_BLK_DEV_IO_TRACE=y CONFIG_BLK_DEV_BSG=y -CONFIG_BLOCK_COMPAT=y # # IO Schedulers @@ -111,7 +111,6 @@ CONFIG_GENERIC_HARDIRQS=y CONFIG_TICK_ONESHOT=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y -CONFIG_GENERIC_CLOCKEVENTS_BUILD=y # CONFIG_SMP is not set CONFIG_CPU_FREQ=y CONFIG_CPU_FREQ_TABLE=m @@ -120,8 +119,6 @@ CONFIG_CPU_FREQ_STAT=m CONFIG_CPU_FREQ_STAT_DETAILS=y CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y # CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set -# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set CONFIG_CPU_FREQ_GOV_PERFORMANCE=y CONFIG_CPU_FREQ_GOV_POWERSAVE=m CONFIG_CPU_FREQ_GOV_USERSPACE=m @@ -216,7 +213,6 @@ CONFIG_INET_TUNNEL=y CONFIG_INET_XFRM_MODE_TRANSPORT=y CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_INET_XFRM_MODE_BEET=y -CONFIG_INET_LRO=y CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set @@ -308,7 +304,6 @@ CONFIG_NET_TCPPROBE=m # # Generic Driver Options # -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y # CONFIG_PREVENT_FIRMWARE_BUILD is not set CONFIG_FW_LOADER=y @@ -360,11 +355,6 @@ CONFIG_IDE_PROC_FS=y # IDE chipset support/bugfixes # CONFIG_IDE_GENERIC=y -# CONFIG_BLK_DEV_PLATFORM is not set - -# -# PCI IDE chipsets support -# CONFIG_BLK_DEV_IDEPCI=y # CONFIG_IDEPCI_SHARE_IRQ is not set CONFIG_IDEPCI_PCIBUS_ORDER=y @@ -401,6 +391,7 @@ CONFIG_BLK_DEV_ALI15X3=y # CONFIG_BLK_DEV_TC86C001 is not set # CONFIG_IDE_ARM is not set CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set # CONFIG_BLK_DEV_HD is not set # @@ -514,8 +505,6 @@ CONFIG_DUMMY=m # CONFIG_MACVLAN is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set -# CONFIG_VETH is not set -# CONFIG_IP1000 is not set # CONFIG_ARCNET is not set # CONFIG_PHYLIB is not set CONFIG_NET_ETHERNET=y @@ -529,16 +518,13 @@ CONFIG_CASSINI=m # CONFIG_NET_VENDOR_3COM is not set # CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set -# CONFIG_IBM_NEW_EMAC_ZMII is not set -# CONFIG_IBM_NEW_EMAC_RGMII is not set -# CONFIG_IBM_NEW_EMAC_TAH is not set -# CONFIG_IBM_NEW_EMAC_EMAC4 is not set CONFIG_NET_PCI=y # CONFIG_PCNET32 is not set # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_B44 is not set # CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set # CONFIG_EEPRO100 is not set # CONFIG_E100 is not set # CONFIG_FEALNX is not set @@ -557,7 +543,6 @@ CONFIG_NETDEV_1000=y CONFIG_E1000=m CONFIG_E1000_NAPI=y # CONFIG_E1000_DISABLE_PACKET_SPLIT is not set -# CONFIG_E1000E is not set # CONFIG_MYRI_SBUS is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set @@ -575,14 +560,11 @@ CONFIG_BNX2=m CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set # CONFIG_CHELSIO_T3 is not set -# CONFIG_IXGBE is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set # CONFIG_MYRI10GE is not set # CONFIG_NETXEN_NIC is not set -# CONFIG_NIU is not set # CONFIG_MLX4_CORE is not set -# CONFIG_TEHUTI is not set # CONFIG_TR is not set # @@ -837,12 +819,6 @@ CONFIG_HWMON=y # CONFIG_SENSORS_W83627EHF is not set # CONFIG_HWMON_DEBUG_CHIP is not set -# -# Sonics Silicon Backplane -# -CONFIG_SSB_POSSIBLE=y -# CONFIG_SSB is not set - # # Multifunction device drivers # @@ -1423,7 +1399,6 @@ CONFIG_ASYNC_MEMCPY=m CONFIG_ASYNC_XOR=m CONFIG_CRYPTO=y CONFIG_CRYPTO_ALGAPI=y -CONFIG_CRYPTO_AEAD=m CONFIG_CRYPTO_BLKCIPHER=y CONFIG_CRYPTO_HASH=y CONFIG_CRYPTO_MANAGER=y @@ -1442,7 +1417,6 @@ CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_CBC=y CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_LRW=m -CONFIG_CRYPTO_XTS=m # CONFIG_CRYPTO_CRYPTD is not set CONFIG_CRYPTO_DES=y CONFIG_CRYPTO_FCRYPT=m @@ -1457,13 +1431,11 @@ CONFIG_CRYPTO_TEA=m CONFIG_CRYPTO_ARC4=m CONFIG_CRYPTO_KHAZAD=m CONFIG_CRYPTO_ANUBIS=m -CONFIG_CRYPTO_SEED=m CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_MICHAEL_MIC=m CONFIG_CRYPTO_CRC32C=m CONFIG_CRYPTO_CAMELLIA=m CONFIG_CRYPTO_TEST=m -CONFIG_CRYPTO_AUTHENC=m CONFIG_CRYPTO_HW=y # diff --git a/trunk/arch/sparc64/kernel/Makefile b/trunk/arch/sparc64/kernel/Makefile index 112c46e66578..40d2f3aae91e 100644 --- a/trunk/arch/sparc64/kernel/Makefile +++ b/trunk/arch/sparc64/kernel/Makefile @@ -18,7 +18,6 @@ obj-$(CONFIG_STACKTRACE) += stacktrace.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_PCI_MSI) += pci_msi.o obj-$(CONFIG_SMP) += smp.o trampoline.o hvtramp.o obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o diff --git a/trunk/arch/sparc64/kernel/auxio.c b/trunk/arch/sparc64/kernel/auxio.c index c55f0293eacd..7b379761e9f8 100644 --- a/trunk/arch/sparc64/kernel/auxio.c +++ b/trunk/arch/sparc64/kernel/auxio.c @@ -148,11 +148,9 @@ static int __devinit auxio_probe(struct of_device *dev, const struct of_device_i } static struct of_platform_driver auxio_driver = { + .name = "auxio", .match_table = auxio_match, .probe = auxio_probe, - .driver = { - .name = "auxio", - }, }; static int __init auxio_init(void) diff --git a/trunk/arch/sparc64/kernel/entry.S b/trunk/arch/sparc64/kernel/entry.S index c9b0d7af64ae..8059531bf0ac 100644 --- a/trunk/arch/sparc64/kernel/entry.S +++ b/trunk/arch/sparc64/kernel/entry.S @@ -429,16 +429,16 @@ do_ivec: stxa %g0, [%g0] ASI_INTR_RECEIVE membar #Sync - sethi %hi(ivector_table_pa), %g2 - ldx [%g2 + %lo(ivector_table_pa)], %g2 - sllx %g3, 4, %g3 + sethi %hi(ivector_table), %g2 + sllx %g3, 3, %g3 + or %g2, %lo(ivector_table), %g2 add %g2, %g3, %g3 - TRAP_LOAD_IRQ_WORK_PA(%g6, %g1) + TRAP_LOAD_IRQ_WORK(%g6, %g1) - ldx [%g6], %g5 - stxa %g5, [%g3] ASI_PHYS_USE_EC - stx %g3, [%g6] + lduw [%g6], %g5 /* g5 = irq_work(cpu) */ + stw %g5, [%g3 + 0x00] /* bucket->irq_chain = g5 */ + stw %g3, [%g6] /* irq_work(cpu) = bucket */ wr %g0, 1 << PIL_DEVICE_IRQ, %set_softint retry do_ivec_xcall: diff --git a/trunk/arch/sparc64/kernel/irq.c b/trunk/arch/sparc64/kernel/irq.c index f3922e5a89f6..23956096b3bf 100644 --- a/trunk/arch/sparc64/kernel/irq.c +++ b/trunk/arch/sparc64/kernel/irq.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -42,7 +43,6 @@ #include #include #include -#include /* UPA nodes send interrupt packet to UltraSparc with first data reg * value low 5 (7 on Starfire) bits holding the IRQ identifier being @@ -52,129 +52,87 @@ * To make processing these packets efficient and race free we use * an array of irq buckets below. The interrupt vector handler in * entry.S feeds incoming packets into per-cpu pil-indexed lists. + * The IVEC handler does not need to act atomically, the PIL dispatch + * code uses CAS to get an atomic snapshot of the list and clear it + * at the same time. * * If you make changes to ino_bucket, please update hand coded assembler * of the vectored interrupt trap handler(s) in entry.S and sun4v_ivec.S */ struct ino_bucket { -/*0x00*/unsigned long __irq_chain_pa; + /* Next handler in per-CPU IRQ worklist. We know that + * bucket pointers have the high 32-bits clear, so to + * save space we only store the bits we need. + */ +/*0x00*/unsigned int irq_chain; /* Virtual interrupt number assigned to this INO. */ -/*0x08*/unsigned int __virt_irq; -/*0x0c*/unsigned int __pad; +/*0x04*/unsigned int virt_irq; }; #define NUM_IVECS (IMAP_INR + 1) -struct ino_bucket *ivector_table; -unsigned long ivector_table_pa; - -/* On several sun4u processors, it is illegal to mix bypass and - * non-bypass accesses. Therefore we access all INO buckets - * using bypass accesses only. +struct ino_bucket ivector_table[NUM_IVECS] __attribute__ ((aligned (SMP_CACHE_BYTES))); + +#define __irq_ino(irq) \ + (((struct ino_bucket *)(unsigned long)(irq)) - &ivector_table[0]) +#define __bucket(irq) ((struct ino_bucket *)(unsigned long)(irq)) +#define __irq(bucket) ((unsigned int)(unsigned long)(bucket)) + +/* This has to be in the main kernel image, it cannot be + * turned into per-cpu data. The reason is that the main + * kernel image is locked into the TLB and this structure + * is accessed from the vectored interrupt trap handler. If + * access to this structure takes a TLB miss it could cause + * the 5-level sparc v9 trap stack to overflow. */ -static unsigned long bucket_get_chain_pa(unsigned long bucket_pa) -{ - unsigned long ret; - - __asm__ __volatile__("ldxa [%1] %2, %0" - : "=&r" (ret) - : "r" (bucket_pa + - offsetof(struct ino_bucket, - __irq_chain_pa)), - "i" (ASI_PHYS_USE_EC)); - - return ret; -} - -static void bucket_clear_chain_pa(unsigned long bucket_pa) -{ - __asm__ __volatile__("stxa %%g0, [%0] %1" - : /* no outputs */ - : "r" (bucket_pa + - offsetof(struct ino_bucket, - __irq_chain_pa)), - "i" (ASI_PHYS_USE_EC)); -} - -static unsigned int bucket_get_virt_irq(unsigned long bucket_pa) -{ - unsigned int ret; - - __asm__ __volatile__("lduwa [%1] %2, %0" - : "=&r" (ret) - : "r" (bucket_pa + - offsetof(struct ino_bucket, - __virt_irq)), - "i" (ASI_PHYS_USE_EC)); - - return ret; -} - -static void bucket_set_virt_irq(unsigned long bucket_pa, - unsigned int virt_irq) -{ - __asm__ __volatile__("stwa %0, [%1] %2" - : /* no outputs */ - : "r" (virt_irq), - "r" (bucket_pa + - offsetof(struct ino_bucket, - __virt_irq)), - "i" (ASI_PHYS_USE_EC)); -} - -#define irq_work_pa(__cpu) &(trap_block[(__cpu)].irq_worklist_pa) +#define irq_work(__cpu) &(trap_block[(__cpu)].irq_worklist) static struct { + unsigned int irq; unsigned int dev_handle; unsigned int dev_ino; - unsigned int in_use; -} virt_irq_table[NR_IRQS]; -static DEFINE_SPINLOCK(virt_irq_alloc_lock); +} virt_to_real_irq_table[NR_IRQS]; -unsigned char virt_irq_alloc(unsigned int dev_handle, - unsigned int dev_ino) +static unsigned char virt_irq_alloc(unsigned int real_irq) { - unsigned long flags; unsigned char ent; BUILD_BUG_ON(NR_IRQS >= 256); - spin_lock_irqsave(&virt_irq_alloc_lock, flags); - for (ent = 1; ent < NR_IRQS; ent++) { - if (!virt_irq_table[ent].in_use) + if (!virt_to_real_irq_table[ent].irq) break; } if (ent >= NR_IRQS) { printk(KERN_ERR "IRQ: Out of virtual IRQs.\n"); - ent = 0; - } else { - virt_irq_table[ent].dev_handle = dev_handle; - virt_irq_table[ent].dev_ino = dev_ino; - virt_irq_table[ent].in_use = 1; + return 0; } - spin_unlock_irqrestore(&virt_irq_alloc_lock, flags); + virt_to_real_irq_table[ent].irq = real_irq; return ent; } #ifdef CONFIG_PCI_MSI -void virt_irq_free(unsigned int virt_irq) +static void virt_irq_free(unsigned int virt_irq) { - unsigned long flags; + unsigned int real_irq; if (virt_irq >= NR_IRQS) return; - spin_lock_irqsave(&virt_irq_alloc_lock, flags); + real_irq = virt_to_real_irq_table[virt_irq].irq; + virt_to_real_irq_table[virt_irq].irq = 0; - virt_irq_table[virt_irq].in_use = 0; - - spin_unlock_irqrestore(&virt_irq_alloc_lock, flags); + __bucket(real_irq)->virt_irq = 0; } #endif +static unsigned int virt_to_real_irq(unsigned char virt_irq) +{ + return virt_to_real_irq_table[virt_irq].irq; +} + /* * /proc/interrupts printing: */ @@ -259,8 +217,38 @@ struct irq_handler_data { void (*pre_handler)(unsigned int, void *, void *); void *pre_handler_arg1; void *pre_handler_arg2; + + u32 msi; }; +void sparc64_set_msi(unsigned int virt_irq, u32 msi) +{ + struct irq_handler_data *data = get_irq_chip_data(virt_irq); + + if (data) + data->msi = msi; +} + +u32 sparc64_get_msi(unsigned int virt_irq) +{ + struct irq_handler_data *data = get_irq_chip_data(virt_irq); + + if (data) + return data->msi; + return 0xffffffff; +} + +static inline struct ino_bucket *virt_irq_to_bucket(unsigned int virt_irq) +{ + unsigned int real_irq = virt_to_real_irq(virt_irq); + struct ino_bucket *bucket = NULL; + + if (likely(real_irq)) + bucket = __bucket(real_irq); + + return bucket; +} + #ifdef CONFIG_SMP static int irq_choose_cpu(unsigned int virt_irq) { @@ -360,152 +348,201 @@ static void sun4u_irq_end(unsigned int virt_irq) static void sun4v_irq_enable(unsigned int virt_irq) { - unsigned int ino = virt_irq_table[virt_irq].dev_ino; - unsigned long cpuid = irq_choose_cpu(virt_irq); - int err; + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); + unsigned int ino = bucket - &ivector_table[0]; + + if (likely(bucket)) { + unsigned long cpuid; + int err; - err = sun4v_intr_settarget(ino, cpuid); - if (err != HV_EOK) - printk(KERN_ERR "sun4v_intr_settarget(%x,%lu): " - "err(%d)\n", ino, cpuid, err); - err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE); - if (err != HV_EOK) - printk(KERN_ERR "sun4v_intr_setstate(%x): " - "err(%d)\n", ino, err); - err = sun4v_intr_setenabled(ino, HV_INTR_ENABLED); - if (err != HV_EOK) - printk(KERN_ERR "sun4v_intr_setenabled(%x): err(%d)\n", - ino, err); + cpuid = irq_choose_cpu(virt_irq); + + err = sun4v_intr_settarget(ino, cpuid); + if (err != HV_EOK) + printk(KERN_ERR "sun4v_intr_settarget(%x,%lu): " + "err(%d)\n", ino, cpuid, err); + err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE); + if (err != HV_EOK) + printk(KERN_ERR "sun4v_intr_setstate(%x): " + "err(%d)\n", ino, err); + err = sun4v_intr_setenabled(ino, HV_INTR_ENABLED); + if (err != HV_EOK) + printk(KERN_ERR "sun4v_intr_setenabled(%x): err(%d)\n", + ino, err); + } } static void sun4v_set_affinity(unsigned int virt_irq, cpumask_t mask) { - unsigned int ino = virt_irq_table[virt_irq].dev_ino; - unsigned long cpuid = irq_choose_cpu(virt_irq); - int err; + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); + unsigned int ino = bucket - &ivector_table[0]; - err = sun4v_intr_settarget(ino, cpuid); - if (err != HV_EOK) - printk(KERN_ERR "sun4v_intr_settarget(%x,%lu): " - "err(%d)\n", ino, cpuid, err); + if (likely(bucket)) { + unsigned long cpuid; + int err; + + cpuid = irq_choose_cpu(virt_irq); + + err = sun4v_intr_settarget(ino, cpuid); + if (err != HV_EOK) + printk(KERN_ERR "sun4v_intr_settarget(%x,%lu): " + "err(%d)\n", ino, cpuid, err); + } } static void sun4v_irq_disable(unsigned int virt_irq) { - unsigned int ino = virt_irq_table[virt_irq].dev_ino; - int err; + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); + unsigned int ino = bucket - &ivector_table[0]; + + if (likely(bucket)) { + int err; + + err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED); + if (err != HV_EOK) + printk(KERN_ERR "sun4v_intr_setenabled(%x): " + "err(%d)\n", ino, err); + } +} + +#ifdef CONFIG_PCI_MSI +static void sun4v_msi_enable(unsigned int virt_irq) +{ + sun4v_irq_enable(virt_irq); + unmask_msi_irq(virt_irq); +} - err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED); - if (err != HV_EOK) - printk(KERN_ERR "sun4v_intr_setenabled(%x): " - "err(%d)\n", ino, err); +static void sun4v_msi_disable(unsigned int virt_irq) +{ + mask_msi_irq(virt_irq); + sun4v_irq_disable(virt_irq); } +#endif static void sun4v_irq_end(unsigned int virt_irq) { - unsigned int ino = virt_irq_table[virt_irq].dev_ino; + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); + unsigned int ino = bucket - &ivector_table[0]; struct irq_desc *desc = irq_desc + virt_irq; - int err; if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) return; - err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE); - if (err != HV_EOK) - printk(KERN_ERR "sun4v_intr_setstate(%x): " - "err(%d)\n", ino, err); + if (likely(bucket)) { + int err; + + err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE); + if (err != HV_EOK) + printk(KERN_ERR "sun4v_intr_setstate(%x): " + "err(%d)\n", ino, err); + } } static void sun4v_virq_enable(unsigned int virt_irq) { - unsigned long cpuid, dev_handle, dev_ino; - int err; - - cpuid = irq_choose_cpu(virt_irq); - - dev_handle = virt_irq_table[virt_irq].dev_handle; - dev_ino = virt_irq_table[virt_irq].dev_ino; - - err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); - if (err != HV_EOK) - printk(KERN_ERR "sun4v_vintr_set_target(%lx,%lx,%lu): " - "err(%d)\n", - dev_handle, dev_ino, cpuid, err); - err = sun4v_vintr_set_state(dev_handle, dev_ino, - HV_INTR_STATE_IDLE); - if (err != HV_EOK) - printk(KERN_ERR "sun4v_vintr_set_state(%lx,%lx," - "HV_INTR_STATE_IDLE): err(%d)\n", - dev_handle, dev_ino, err); - err = sun4v_vintr_set_valid(dev_handle, dev_ino, - HV_INTR_ENABLED); - if (err != HV_EOK) - printk(KERN_ERR "sun4v_vintr_set_state(%lx,%lx," - "HV_INTR_ENABLED): err(%d)\n", - dev_handle, dev_ino, err); + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); + + if (likely(bucket)) { + unsigned long cpuid, dev_handle, dev_ino; + int err; + + cpuid = irq_choose_cpu(virt_irq); + + dev_handle = virt_to_real_irq_table[virt_irq].dev_handle; + dev_ino = virt_to_real_irq_table[virt_irq].dev_ino; + + err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); + if (err != HV_EOK) + printk(KERN_ERR "sun4v_vintr_set_target(%lx,%lx,%lu): " + "err(%d)\n", + dev_handle, dev_ino, cpuid, err); + err = sun4v_vintr_set_state(dev_handle, dev_ino, + HV_INTR_STATE_IDLE); + if (err != HV_EOK) + printk(KERN_ERR "sun4v_vintr_set_state(%lx,%lx," + "HV_INTR_STATE_IDLE): err(%d)\n", + dev_handle, dev_ino, err); + err = sun4v_vintr_set_valid(dev_handle, dev_ino, + HV_INTR_ENABLED); + if (err != HV_EOK) + printk(KERN_ERR "sun4v_vintr_set_state(%lx,%lx," + "HV_INTR_ENABLED): err(%d)\n", + dev_handle, dev_ino, err); + } } static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask) { - unsigned long cpuid, dev_handle, dev_ino; - int err; + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); - cpuid = irq_choose_cpu(virt_irq); + if (likely(bucket)) { + unsigned long cpuid, dev_handle, dev_ino; + int err; - dev_handle = virt_irq_table[virt_irq].dev_handle; - dev_ino = virt_irq_table[virt_irq].dev_ino; + cpuid = irq_choose_cpu(virt_irq); - err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); - if (err != HV_EOK) - printk(KERN_ERR "sun4v_vintr_set_target(%lx,%lx,%lu): " - "err(%d)\n", - dev_handle, dev_ino, cpuid, err); + dev_handle = virt_to_real_irq_table[virt_irq].dev_handle; + dev_ino = virt_to_real_irq_table[virt_irq].dev_ino; + + err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid); + if (err != HV_EOK) + printk(KERN_ERR "sun4v_vintr_set_target(%lx,%lx,%lu): " + "err(%d)\n", + dev_handle, dev_ino, cpuid, err); + } } static void sun4v_virq_disable(unsigned int virt_irq) { - unsigned long dev_handle, dev_ino; - int err; + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); - dev_handle = virt_irq_table[virt_irq].dev_handle; - dev_ino = virt_irq_table[virt_irq].dev_ino; + if (likely(bucket)) { + unsigned long dev_handle, dev_ino; + int err; - err = sun4v_vintr_set_valid(dev_handle, dev_ino, - HV_INTR_DISABLED); - if (err != HV_EOK) - printk(KERN_ERR "sun4v_vintr_set_state(%lx,%lx," - "HV_INTR_DISABLED): err(%d)\n", - dev_handle, dev_ino, err); + dev_handle = virt_to_real_irq_table[virt_irq].dev_handle; + dev_ino = virt_to_real_irq_table[virt_irq].dev_ino; + + err = sun4v_vintr_set_valid(dev_handle, dev_ino, + HV_INTR_DISABLED); + if (err != HV_EOK) + printk(KERN_ERR "sun4v_vintr_set_state(%lx,%lx," + "HV_INTR_DISABLED): err(%d)\n", + dev_handle, dev_ino, err); + } } static void sun4v_virq_end(unsigned int virt_irq) { + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); struct irq_desc *desc = irq_desc + virt_irq; - unsigned long dev_handle, dev_ino; - int err; if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) return; - dev_handle = virt_irq_table[virt_irq].dev_handle; - dev_ino = virt_irq_table[virt_irq].dev_ino; + if (likely(bucket)) { + unsigned long dev_handle, dev_ino; + int err; - err = sun4v_vintr_set_state(dev_handle, dev_ino, - HV_INTR_STATE_IDLE); - if (err != HV_EOK) - printk(KERN_ERR "sun4v_vintr_set_state(%lx,%lx," - "HV_INTR_STATE_IDLE): err(%d)\n", - dev_handle, dev_ino, err); + dev_handle = virt_to_real_irq_table[virt_irq].dev_handle; + dev_ino = virt_to_real_irq_table[virt_irq].dev_ino; + + err = sun4v_vintr_set_state(dev_handle, dev_ino, + HV_INTR_STATE_IDLE); + if (err != HV_EOK) + printk(KERN_ERR "sun4v_vintr_set_state(%lx,%lx," + "HV_INTR_STATE_IDLE): err(%d)\n", + dev_handle, dev_ino, err); + } } static void run_pre_handler(unsigned int virt_irq) { + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); struct irq_handler_data *data = get_irq_chip_data(virt_irq); - unsigned int ino; - ino = virt_irq_table[virt_irq].dev_ino; if (likely(data->pre_handler)) { - data->pre_handler(ino, + data->pre_handler(__irq_ino(__irq(bucket)), data->pre_handler_arg1, data->pre_handler_arg2); } @@ -536,6 +573,28 @@ static struct irq_chip sun4v_irq = { .set_affinity = sun4v_set_affinity, }; +static struct irq_chip sun4v_irq_ack = { + .typename = "sun4v+ack", + .enable = sun4v_irq_enable, + .disable = sun4v_irq_disable, + .ack = run_pre_handler, + .end = sun4v_irq_end, + .set_affinity = sun4v_set_affinity, +}; + +#ifdef CONFIG_PCI_MSI +static struct irq_chip sun4v_msi = { + .typename = "sun4v+msi", + .mask = mask_msi_irq, + .unmask = unmask_msi_irq, + .enable = sun4v_msi_enable, + .disable = sun4v_msi_disable, + .ack = run_pre_handler, + .end = sun4v_irq_end, + .set_affinity = sun4v_set_affinity, +}; +#endif + static struct irq_chip sun4v_virq = { .typename = "vsun4v", .enable = sun4v_virq_enable, @@ -544,48 +603,59 @@ static struct irq_chip sun4v_virq = { .set_affinity = sun4v_virt_set_affinity, }; +static struct irq_chip sun4v_virq_ack = { + .typename = "vsun4v+ack", + .enable = sun4v_virq_enable, + .disable = sun4v_virq_disable, + .ack = run_pre_handler, + .end = sun4v_virq_end, + .set_affinity = sun4v_virt_set_affinity, +}; + void irq_install_pre_handler(int virt_irq, void (*func)(unsigned int, void *, void *), void *arg1, void *arg2) { struct irq_handler_data *data = get_irq_chip_data(virt_irq); - struct irq_chip *chip = get_irq_chip(virt_irq); - - if (WARN_ON(chip == &sun4v_irq || chip == &sun4v_virq)) { - printk(KERN_ERR "IRQ: Trying to install pre-handler on " - "sun4v irq %u\n", virt_irq); - return; - } + struct irq_chip *chip; data->pre_handler = func; data->pre_handler_arg1 = arg1; data->pre_handler_arg2 = arg2; - if (chip == &sun4u_irq_ack) + chip = get_irq_chip(virt_irq); + if (chip == &sun4u_irq_ack || + chip == &sun4v_irq_ack || + chip == &sun4v_virq_ack +#ifdef CONFIG_PCI_MSI + || chip == &sun4v_msi +#endif + ) return; - set_irq_chip(virt_irq, &sun4u_irq_ack); + chip = (chip == &sun4u_irq ? + &sun4u_irq_ack : + (chip == &sun4v_irq ? + &sun4v_irq_ack : &sun4v_virq_ack)); + set_irq_chip(virt_irq, chip); } unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap) { struct ino_bucket *bucket; struct irq_handler_data *data; - unsigned int virt_irq; int ino; BUG_ON(tlb_type == hypervisor); ino = (upa_readq(imap) & (IMAP_IGN | IMAP_INO)) + inofixup; bucket = &ivector_table[ino]; - virt_irq = bucket_get_virt_irq(__pa(bucket)); - if (!virt_irq) { - virt_irq = virt_irq_alloc(0, ino); - bucket_set_virt_irq(__pa(bucket), virt_irq); - set_irq_chip(virt_irq, &sun4u_irq); + if (!bucket->virt_irq) { + bucket->virt_irq = virt_irq_alloc(__irq(bucket)); + set_irq_chip(bucket->virt_irq, &sun4u_irq); } - data = get_irq_chip_data(virt_irq); + data = get_irq_chip_data(bucket->virt_irq); if (unlikely(data)) goto out; @@ -594,13 +664,13 @@ unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap) prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n"); prom_halt(); } - set_irq_chip_data(virt_irq, data); + set_irq_chip_data(bucket->virt_irq, data); data->imap = imap; data->iclr = iclr; out: - return virt_irq; + return bucket->virt_irq; } static unsigned int sun4v_build_common(unsigned long sysino, @@ -608,19 +678,16 @@ static unsigned int sun4v_build_common(unsigned long sysino, { struct ino_bucket *bucket; struct irq_handler_data *data; - unsigned int virt_irq; BUG_ON(tlb_type != hypervisor); bucket = &ivector_table[sysino]; - virt_irq = bucket_get_virt_irq(__pa(bucket)); - if (!virt_irq) { - virt_irq = virt_irq_alloc(0, sysino); - bucket_set_virt_irq(__pa(bucket), virt_irq); - set_irq_chip(virt_irq, chip); + if (!bucket->virt_irq) { + bucket->virt_irq = virt_irq_alloc(__irq(bucket)); + set_irq_chip(bucket->virt_irq, chip); } - data = get_irq_chip_data(virt_irq); + data = get_irq_chip_data(bucket->virt_irq); if (unlikely(data)) goto out; @@ -629,7 +696,7 @@ static unsigned int sun4v_build_common(unsigned long sysino, prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n"); prom_halt(); } - set_irq_chip_data(virt_irq, data); + set_irq_chip_data(bucket->virt_irq, data); /* Catch accidental accesses to these things. IMAP/ICLR handling * is done by hypervisor calls on sun4v platforms, not by direct @@ -639,7 +706,7 @@ static unsigned int sun4v_build_common(unsigned long sysino, data->iclr = ~0UL; out: - return virt_irq; + return bucket->virt_irq; } unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino) @@ -651,52 +718,86 @@ unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino) unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino) { - struct irq_handler_data *data; + unsigned long sysino, hv_err; + unsigned int virq; + + BUG_ON(devhandle & devino); + + sysino = devhandle | devino; + BUG_ON(sysino & ~(IMAP_IGN | IMAP_INO)); + + hv_err = sun4v_vintr_set_cookie(devhandle, devino, sysino); + if (hv_err) { + prom_printf("IRQ: Fatal, cannot set cookie for [%x:%x] " + "err=%lu\n", devhandle, devino, hv_err); + prom_halt(); + } + + virq = sun4v_build_common(sysino, &sun4v_virq); + + virt_to_real_irq_table[virq].dev_handle = devhandle; + virt_to_real_irq_table[virq].dev_ino = devino; + + return virq; +} + +#ifdef CONFIG_PCI_MSI +unsigned int sun4v_build_msi(u32 devhandle, unsigned int *virt_irq_p, + unsigned int msi_start, unsigned int msi_end) +{ struct ino_bucket *bucket; - unsigned long hv_err, cookie; - unsigned int virt_irq; + struct irq_handler_data *data; + unsigned long sysino; + unsigned int devino; - bucket = kzalloc(sizeof(struct ino_bucket), GFP_ATOMIC); - if (unlikely(!bucket)) - return 0; - __flush_dcache_range((unsigned long) bucket, - ((unsigned long) bucket + - sizeof(struct ino_bucket))); + BUG_ON(tlb_type != hypervisor); - virt_irq = virt_irq_alloc(devhandle, devino); - bucket_set_virt_irq(__pa(bucket), virt_irq); - set_irq_chip(virt_irq, &sun4v_virq); + /* Find a free devino in the given range. */ + for (devino = msi_start; devino < msi_end; devino++) { + sysino = sun4v_devino_to_sysino(devhandle, devino); + bucket = &ivector_table[sysino]; + if (!bucket->virt_irq) + break; + } + if (devino >= msi_end) + return -ENOSPC; - data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); - if (unlikely(!data)) - return 0; + sysino = sun4v_devino_to_sysino(devhandle, devino); + bucket = &ivector_table[sysino]; + bucket->virt_irq = virt_irq_alloc(__irq(bucket)); + *virt_irq_p = bucket->virt_irq; + set_irq_chip(bucket->virt_irq, &sun4v_msi); - set_irq_chip_data(virt_irq, data); + data = get_irq_chip_data(bucket->virt_irq); + if (unlikely(data)) + return devino; + + data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC); + if (unlikely(!data)) { + virt_irq_free(*virt_irq_p); + return -ENOMEM; + } + set_irq_chip_data(bucket->virt_irq, data); - /* Catch accidental accesses to these things. IMAP/ICLR handling - * is done by hypervisor calls on sun4v platforms, not by direct - * register accesses. - */ data->imap = ~0UL; data->iclr = ~0UL; - cookie = ~__pa(bucket); - hv_err = sun4v_vintr_set_cookie(devhandle, devino, cookie); - if (hv_err) { - prom_printf("IRQ: Fatal, cannot set cookie for [%x:%x] " - "err=%lu\n", devhandle, devino, hv_err); - prom_halt(); - } + return devino; +} - return virt_irq; +void sun4v_destroy_msi(unsigned int virt_irq) +{ + virt_irq_free(virt_irq); } +#endif void ack_bad_irq(unsigned int virt_irq) { - unsigned int ino = virt_irq_table[virt_irq].dev_ino; + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); + unsigned int ino = 0xdeadbeef; - if (!ino) - ino = 0xdeadbeef; + if (bucket) + ino = bucket - &ivector_table[0]; printk(KERN_CRIT "Unexpected IRQ from ino[%x] virt_irq[%u]\n", ino, virt_irq); @@ -704,7 +805,7 @@ void ack_bad_irq(unsigned int virt_irq) void handler_irq(int irq, struct pt_regs *regs) { - unsigned long pstate, bucket_pa; + struct ino_bucket *bucket; struct pt_regs *old_regs; clear_softint(1 << irq); @@ -712,28 +813,15 @@ void handler_irq(int irq, struct pt_regs *regs) old_regs = set_irq_regs(regs); irq_enter(); - /* Grab an atomic snapshot of the pending IVECs. */ - __asm__ __volatile__("rdpr %%pstate, %0\n\t" - "wrpr %0, %3, %%pstate\n\t" - "ldx [%2], %1\n\t" - "stx %%g0, [%2]\n\t" - "wrpr %0, 0x0, %%pstate\n\t" - : "=&r" (pstate), "=&r" (bucket_pa) - : "r" (irq_work_pa(smp_processor_id())), - "i" (PSTATE_IE) - : "memory"); - - while (bucket_pa) { - unsigned long next_pa; - unsigned int virt_irq; + /* Sliiiick... */ + bucket = __bucket(xchg32(irq_work(smp_processor_id()), 0)); + while (bucket) { + struct ino_bucket *next = __bucket(bucket->irq_chain); - next_pa = bucket_get_chain_pa(bucket_pa); - virt_irq = bucket_get_virt_irq(bucket_pa); - bucket_clear_chain_pa(bucket_pa); + bucket->irq_chain = 0; + __do_IRQ(bucket->virt_irq); - __do_IRQ(virt_irq); - - bucket_pa = next_pa; + bucket = next; } irq_exit(); @@ -833,7 +921,7 @@ void init_irqwork_curcpu(void) { int cpu = hard_smp_processor_id(); - trap_block[cpu].irq_worklist_pa = 0UL; + trap_block[cpu].irq_worklist = 0; } /* Please be very careful with register_one_mondo() and @@ -947,21 +1035,9 @@ static struct irqaction timer_irq_action = { /* Only invoked on boot processor. */ void __init init_IRQ(void) { - unsigned long size; - map_prom_timers(); kill_prom_timer(); - - size = sizeof(struct ino_bucket) * NUM_IVECS; - ivector_table = alloc_bootmem_low(size); - if (!ivector_table) { - prom_printf("Fatal error, cannot allocate ivector_table\n"); - prom_halt(); - } - __flush_dcache_range((unsigned long) ivector_table, - ((unsigned long) ivector_table) + size); - - ivector_table_pa = __pa(ivector_table); + memset(&ivector_table[0], 0, sizeof(ivector_table)); if (tlb_type == hypervisor) sun4v_init_mondo_queues(); diff --git a/trunk/arch/sparc64/kernel/of_device.c b/trunk/arch/sparc64/kernel/of_device.c index 42d779866fba..4cc77485f536 100644 --- a/trunk/arch/sparc64/kernel/of_device.c +++ b/trunk/arch/sparc64/kernel/of_device.c @@ -872,10 +872,7 @@ __setup("of_debug=", of_debug); int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus) { /* initialize common driver fields */ - if (!drv->driver.name) - drv->driver.name = drv->name; - if (!drv->driver.owner) - drv->driver.owner = drv->owner; + drv->driver.name = drv->name; drv->driver.bus = bus; /* register with core */ diff --git a/trunk/arch/sparc64/kernel/pci.c b/trunk/arch/sparc64/kernel/pci.c index 9b808640a193..e8dac81d8a0d 100644 --- a/trunk/arch/sparc64/kernel/pci.c +++ b/trunk/arch/sparc64/kernel/pci.c @@ -29,6 +29,8 @@ #include "pci_impl.h" +unsigned long pci_memspace_mask = 0xffffffffUL; + #ifndef CONFIG_PCI /* A "nop" PCI implementation. */ asmlinkage int sys_pciconfig_read(unsigned long bus, unsigned long dfn, @@ -1064,8 +1066,8 @@ static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struc return 0; } -/* Adjust vm_pgoff of VMA such that it is the physical page offset - * corresponding to the 32-bit pci bus offset for DEV requested by the user. +/* Adjust vm_pgoff of VMA such that it is the physical page offset corresponding + * to the 32-bit pci bus offset for DEV requested by the user. * * Basically, the user finds the base address for his device which he wishes * to mmap. They read the 32-bit value from the config space base register, @@ -1074,35 +1076,21 @@ static int __pci_mmap_make_offset_bus(struct pci_dev *pdev, struct vm_area_struc * * Returns negative error code on failure, zero on success. */ -static int __pci_mmap_make_offset(struct pci_dev *pdev, - struct vm_area_struct *vma, +static int __pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma, enum pci_mmap_state mmap_state) { - unsigned long user_paddr, user_size; - int i, err; + unsigned long user_offset = vma->vm_pgoff << PAGE_SHIFT; + unsigned long user32 = user_offset & pci_memspace_mask; + unsigned long largest_base, this_base, addr32; + int i; - /* First compute the physical address in vma->vm_pgoff, - * making sure the user offset is within range in the - * appropriate PCI space. - */ - err = __pci_mmap_make_offset_bus(pdev, vma, mmap_state); - if (err) - return err; - - /* If this is a mapping on a host bridge, any address - * is OK. - */ - if ((pdev->class >> 8) == PCI_CLASS_BRIDGE_HOST) - return err; - - /* Otherwise make sure it's in the range for one of the - * device's resources. - */ - user_paddr = vma->vm_pgoff << PAGE_SHIFT; - user_size = vma->vm_end - vma->vm_start; + if ((dev->class >> 8) == PCI_CLASS_BRIDGE_HOST) + return __pci_mmap_make_offset_bus(dev, vma, mmap_state); + /* Figure out which base address this is for. */ + largest_base = 0UL; for (i = 0; i <= PCI_ROM_RESOURCE; i++) { - struct resource *rp = &pdev->resource[i]; + struct resource *rp = &dev->resource[i]; /* Active? */ if (!rp->flags) @@ -1120,14 +1108,26 @@ static int __pci_mmap_make_offset(struct pci_dev *pdev, continue; } - if ((rp->start <= user_paddr) && - (user_paddr + user_size) <= (rp->end + 1UL)) - break; + this_base = rp->start; + + addr32 = (this_base & PAGE_MASK) & pci_memspace_mask; + + if (mmap_state == pci_mmap_io) + addr32 &= 0xffffff; + + if (addr32 <= user32 && this_base > largest_base) + largest_base = this_base; } - if (i > PCI_ROM_RESOURCE) + if (largest_base == 0UL) return -EINVAL; + /* Now construct the final physical address. */ + if (mmap_state == pci_mmap_io) + vma->vm_pgoff = (((largest_base & ~0xffffffUL) | user32) >> PAGE_SHIFT); + else + vma->vm_pgoff = (((largest_base & ~(pci_memspace_mask)) | user32) >> PAGE_SHIFT); + return 0; } diff --git a/trunk/arch/sparc64/kernel/pci_fire.c b/trunk/arch/sparc64/kernel/pci_fire.c index fef3b37487bf..14d67fe21ab2 100644 --- a/trunk/arch/sparc64/kernel/pci_fire.c +++ b/trunk/arch/sparc64/kernel/pci_fire.c @@ -6,12 +6,9 @@ #include #include #include -#include -#include #include #include -#include #include "pci_impl.h" @@ -87,266 +84,6 @@ static int pci_fire_pbm_iommu_init(struct pci_pbm_info *pbm) return 0; } -#ifdef CONFIG_PCI_MSI -struct pci_msiq_entry { - u64 word0; -#define MSIQ_WORD0_RESV 0x8000000000000000UL -#define MSIQ_WORD0_FMT_TYPE 0x7f00000000000000UL -#define MSIQ_WORD0_FMT_TYPE_SHIFT 56 -#define MSIQ_WORD0_LEN 0x00ffc00000000000UL -#define MSIQ_WORD0_LEN_SHIFT 46 -#define MSIQ_WORD0_ADDR0 0x00003fff00000000UL -#define MSIQ_WORD0_ADDR0_SHIFT 32 -#define MSIQ_WORD0_RID 0x00000000ffff0000UL -#define MSIQ_WORD0_RID_SHIFT 16 -#define MSIQ_WORD0_DATA0 0x000000000000ffffUL -#define MSIQ_WORD0_DATA0_SHIFT 0 - -#define MSIQ_TYPE_MSG 0x6 -#define MSIQ_TYPE_MSI32 0xb -#define MSIQ_TYPE_MSI64 0xf - - u64 word1; -#define MSIQ_WORD1_ADDR1 0xffffffffffff0000UL -#define MSIQ_WORD1_ADDR1_SHIFT 16 -#define MSIQ_WORD1_DATA1 0x000000000000ffffUL -#define MSIQ_WORD1_DATA1_SHIFT 0 - - u64 resv[6]; -}; - -/* All MSI registers are offset from pbm->pbm_regs */ -#define EVENT_QUEUE_BASE_ADDR_REG 0x010000UL -#define EVENT_QUEUE_BASE_ADDR_ALL_ONES 0xfffc000000000000UL - -#define EVENT_QUEUE_CONTROL_SET(EQ) (0x011000UL + (EQ) * 0x8UL) -#define EVENT_QUEUE_CONTROL_SET_OFLOW 0x0200000000000000UL -#define EVENT_QUEUE_CONTROL_SET_EN 0x0000100000000000UL - -#define EVENT_QUEUE_CONTROL_CLEAR(EQ) (0x011200UL + (EQ) * 0x8UL) -#define EVENT_QUEUE_CONTROL_CLEAR_OF 0x0200000000000000UL -#define EVENT_QUEUE_CONTROL_CLEAR_E2I 0x0000800000000000UL -#define EVENT_QUEUE_CONTROL_CLEAR_DIS 0x0000100000000000UL - -#define EVENT_QUEUE_STATE(EQ) (0x011400UL + (EQ) * 0x8UL) -#define EVENT_QUEUE_STATE_MASK 0x0000000000000007UL -#define EVENT_QUEUE_STATE_IDLE 0x0000000000000001UL -#define EVENT_QUEUE_STATE_ACTIVE 0x0000000000000002UL -#define EVENT_QUEUE_STATE_ERROR 0x0000000000000004UL - -#define EVENT_QUEUE_TAIL(EQ) (0x011600UL + (EQ) * 0x8UL) -#define EVENT_QUEUE_TAIL_OFLOW 0x0200000000000000UL -#define EVENT_QUEUE_TAIL_VAL 0x000000000000007fUL - -#define EVENT_QUEUE_HEAD(EQ) (0x011800UL + (EQ) * 0x8UL) -#define EVENT_QUEUE_HEAD_VAL 0x000000000000007fUL - -#define MSI_MAP(MSI) (0x020000UL + (MSI) * 0x8UL) -#define MSI_MAP_VALID 0x8000000000000000UL -#define MSI_MAP_EQWR_N 0x4000000000000000UL -#define MSI_MAP_EQNUM 0x000000000000003fUL - -#define MSI_CLEAR(MSI) (0x028000UL + (MSI) * 0x8UL) -#define MSI_CLEAR_EQWR_N 0x4000000000000000UL - -#define IMONDO_DATA0 0x02C000UL -#define IMONDO_DATA0_DATA 0xffffffffffffffc0UL - -#define IMONDO_DATA1 0x02C008UL -#define IMONDO_DATA1_DATA 0xffffffffffffffffUL - -#define MSI_32BIT_ADDR 0x034000UL -#define MSI_32BIT_ADDR_VAL 0x00000000ffff0000UL - -#define MSI_64BIT_ADDR 0x034008UL -#define MSI_64BIT_ADDR_VAL 0xffffffffffff0000UL - -static int pci_fire_get_head(struct pci_pbm_info *pbm, unsigned long msiqid, - unsigned long *head) -{ - *head = fire_read(pbm->pbm_regs + EVENT_QUEUE_HEAD(msiqid)); - return 0; -} - -static int pci_fire_dequeue_msi(struct pci_pbm_info *pbm, unsigned long msiqid, - unsigned long *head, unsigned long *msi) -{ - unsigned long type_fmt, type, msi_num; - struct pci_msiq_entry *base, *ep; - - base = (pbm->msi_queues + ((msiqid - pbm->msiq_first) * 8192)); - ep = &base[*head]; - - if ((ep->word0 & MSIQ_WORD0_FMT_TYPE) == 0) - return 0; - - type_fmt = ((ep->word0 & MSIQ_WORD0_FMT_TYPE) >> - MSIQ_WORD0_FMT_TYPE_SHIFT); - type = (type_fmt >> 3); - if (unlikely(type != MSIQ_TYPE_MSI32 && - type != MSIQ_TYPE_MSI64)) - return -EINVAL; - - *msi = msi_num = ((ep->word0 & MSIQ_WORD0_DATA0) >> - MSIQ_WORD0_DATA0_SHIFT); - - fire_write(pbm->pbm_regs + MSI_CLEAR(msi_num), - MSI_CLEAR_EQWR_N); - - /* Clear the entry. */ - ep->word0 &= ~MSIQ_WORD0_FMT_TYPE; - - /* Go to next entry in ring. */ - (*head)++; - if (*head >= pbm->msiq_ent_count) - *head = 0; - - return 1; -} - -static int pci_fire_set_head(struct pci_pbm_info *pbm, unsigned long msiqid, - unsigned long head) -{ - fire_write(pbm->pbm_regs + EVENT_QUEUE_HEAD(msiqid), head); - return 0; -} - -static int pci_fire_msi_setup(struct pci_pbm_info *pbm, unsigned long msiqid, - unsigned long msi, int is_msi64) -{ - u64 val; - - val = fire_read(pbm->pbm_regs + MSI_MAP(msi)); - val &= ~(MSI_MAP_EQNUM); - val |= msiqid; - fire_write(pbm->pbm_regs + MSI_MAP(msi), val); - - fire_write(pbm->pbm_regs + MSI_CLEAR(msi), - MSI_CLEAR_EQWR_N); - - val = fire_read(pbm->pbm_regs + MSI_MAP(msi)); - val |= MSI_MAP_VALID; - fire_write(pbm->pbm_regs + MSI_MAP(msi), val); - - return 0; -} - -static int pci_fire_msi_teardown(struct pci_pbm_info *pbm, unsigned long msi) -{ - unsigned long msiqid; - u64 val; - - val = fire_read(pbm->pbm_regs + MSI_MAP(msi)); - msiqid = (val & MSI_MAP_EQNUM); - - val &= ~MSI_MAP_VALID; - - fire_write(pbm->pbm_regs + MSI_MAP(msi), val); - - return 0; -} - -static int pci_fire_msiq_alloc(struct pci_pbm_info *pbm) -{ - unsigned long pages, order, i; - - order = get_order(512 * 1024); - pages = __get_free_pages(GFP_KERNEL | __GFP_COMP, order); - if (pages == 0UL) { - printk(KERN_ERR "MSI: Cannot allocate MSI queues (o=%lu).\n", - order); - return -ENOMEM; - } - memset((char *)pages, 0, PAGE_SIZE << order); - pbm->msi_queues = (void *) pages; - - fire_write(pbm->pbm_regs + EVENT_QUEUE_BASE_ADDR_REG, - (EVENT_QUEUE_BASE_ADDR_ALL_ONES | - __pa(pbm->msi_queues))); - - fire_write(pbm->pbm_regs + IMONDO_DATA0, - pbm->portid << 6); - fire_write(pbm->pbm_regs + IMONDO_DATA1, 0); - - fire_write(pbm->pbm_regs + MSI_32BIT_ADDR, - pbm->msi32_start); - fire_write(pbm->pbm_regs + MSI_64BIT_ADDR, - pbm->msi64_start); - - for (i = 0; i < pbm->msiq_num; i++) { - fire_write(pbm->pbm_regs + EVENT_QUEUE_HEAD(i), 0); - fire_write(pbm->pbm_regs + EVENT_QUEUE_TAIL(i), 0); - } - - return 0; -} - -static void pci_fire_msiq_free(struct pci_pbm_info *pbm) -{ - unsigned long pages, order; - - order = get_order(512 * 1024); - pages = (unsigned long) pbm->msi_queues; - - free_pages(pages, order); - - pbm->msi_queues = NULL; -} - -static int pci_fire_msiq_build_irq(struct pci_pbm_info *pbm, - unsigned long msiqid, - unsigned long devino) -{ - unsigned long cregs = (unsigned long) pbm->pbm_regs; - unsigned long imap_reg, iclr_reg, int_ctrlr; - unsigned int virt_irq; - int fixup; - u64 val; - - imap_reg = cregs + (0x001000UL + (devino * 0x08UL)); - iclr_reg = cregs + (0x001400UL + (devino * 0x08UL)); - - /* XXX iterate amongst the 4 IRQ controllers XXX */ - int_ctrlr = (1UL << 6); - - val = fire_read(imap_reg); - val |= (1UL << 63) | int_ctrlr; - fire_write(imap_reg, val); - - fixup = ((pbm->portid << 6) | devino) - int_ctrlr; - - virt_irq = build_irq(fixup, iclr_reg, imap_reg); - if (!virt_irq) - return -ENOMEM; - - fire_write(pbm->pbm_regs + - EVENT_QUEUE_CONTROL_SET(msiqid), - EVENT_QUEUE_CONTROL_SET_EN); - - return virt_irq; -} - -static const struct sparc64_msiq_ops pci_fire_msiq_ops = { - .get_head = pci_fire_get_head, - .dequeue_msi = pci_fire_dequeue_msi, - .set_head = pci_fire_set_head, - .msi_setup = pci_fire_msi_setup, - .msi_teardown = pci_fire_msi_teardown, - .msiq_alloc = pci_fire_msiq_alloc, - .msiq_free = pci_fire_msiq_free, - .msiq_build_irq = pci_fire_msiq_build_irq, -}; - -static void pci_fire_msi_init(struct pci_pbm_info *pbm) -{ - sparc64_pbm_msi_init(pbm, &pci_fire_msiq_ops); -} -#else /* CONFIG_PCI_MSI */ -static void pci_fire_msi_init(struct pci_pbm_info *pbm) -{ -} -#endif /* !(CONFIG_PCI_MSI) */ - /* Based at pbm->controller_regs */ #define FIRE_PARITY_CONTROL 0x470010UL #define FIRE_PARITY_ENAB 0x8000000000000000UL @@ -439,7 +176,6 @@ static int pci_fire_pbm_init(struct pci_controller_info *p, { const struct linux_prom64_registers *regs; struct pci_pbm_info *pbm; - int err; if ((portid & 1) == 0) pbm = &p->pbm_A; @@ -472,13 +208,7 @@ static int pci_fire_pbm_init(struct pci_controller_info *p, pci_fire_hw_init(pbm); - err = pci_fire_pbm_iommu_init(pbm); - if (err) - return err; - - pci_fire_msi_init(pbm); - - return 0; + return pci_fire_pbm_iommu_init(pbm); } static inline int portid_compare(u32 x, u32 y) @@ -519,6 +249,13 @@ void fire_pci_init(struct device_node *dp, const char *model_name) p->pbm_B.iommu = iommu; + /* XXX MSI support XXX */ + + /* Like PSYCHO and SCHIZO we have a 2GB aligned area + * for memory space. + */ + pci_memspace_mask = 0x7fffffffUL; + if (pci_fire_pbm_init(p, dp, portid)) goto fatal_memory_error; diff --git a/trunk/arch/sparc64/kernel/pci_impl.h b/trunk/arch/sparc64/kernel/pci_impl.h index 4a50da13ce48..f660c2b685eb 100644 --- a/trunk/arch/sparc64/kernel/pci_impl.h +++ b/trunk/arch/sparc64/kernel/pci_impl.h @@ -29,33 +29,6 @@ #define PCI_STC_FLUSHFLAG_SET(STC) \ (*((STC)->strbuf_flushflag) != 0UL) -#ifdef CONFIG_PCI_MSI -struct pci_pbm_info; -struct sparc64_msiq_ops { - int (*get_head)(struct pci_pbm_info *pbm, unsigned long msiqid, - unsigned long *head); - int (*dequeue_msi)(struct pci_pbm_info *pbm, unsigned long msiqid, - unsigned long *head, unsigned long *msi); - int (*set_head)(struct pci_pbm_info *pbm, unsigned long msiqid, - unsigned long head); - int (*msi_setup)(struct pci_pbm_info *pbm, unsigned long msiqid, - unsigned long msi, int is_msi64); - int (*msi_teardown)(struct pci_pbm_info *pbm, unsigned long msi); - int (*msiq_alloc)(struct pci_pbm_info *pbm); - void (*msiq_free)(struct pci_pbm_info *pbm); - int (*msiq_build_irq)(struct pci_pbm_info *pbm, unsigned long msiqid, - unsigned long devino); -}; - -extern void sparc64_pbm_msi_init(struct pci_pbm_info *pbm, - const struct sparc64_msiq_ops *ops); - -struct sparc64_msiq_cookie { - struct pci_pbm_info *pbm; - unsigned long msiqid; -}; -#endif - struct pci_controller_info; struct pci_pbm_info { @@ -117,8 +90,6 @@ struct pci_pbm_info { u32 msiq_ent_count; u32 msiq_first; u32 msiq_first_devino; - u32 msiq_rotor; - struct sparc64_msiq_cookie *msiq_irq_cookies; u32 msi_num; u32 msi_first; u32 msi_data_mask; @@ -129,11 +100,9 @@ struct pci_pbm_info { u32 msi64_len; void *msi_queues; unsigned long *msi_bitmap; - unsigned int *msi_irq_table; int (*setup_msi_irq)(unsigned int *virt_irq_p, struct pci_dev *pdev, struct msi_desc *entry); void (*teardown_msi_irq)(unsigned int virt_irq, struct pci_dev *pdev); - const struct sparc64_msiq_ops *msi_ops; #endif /* !(CONFIG_PCI_MSI) */ /* This PBM's streaming buffer. */ @@ -157,6 +126,7 @@ struct pci_controller_info { }; extern struct pci_pbm_info *pci_pbm_root; +extern unsigned long pci_memspace_mask; extern int pci_num_pbms; diff --git a/trunk/arch/sparc64/kernel/pci_msi.c b/trunk/arch/sparc64/kernel/pci_msi.c deleted file mode 100644 index 31a165fd3e48..000000000000 --- a/trunk/arch/sparc64/kernel/pci_msi.c +++ /dev/null @@ -1,433 +0,0 @@ -/* pci_msi.c: Sparc64 MSI support common layer. - * - * Copyright (C) 2007 David S. Miller (davem@davemloft.net) - */ -#include -#include -#include - -#include "pci_impl.h" - -static irqreturn_t sparc64_msiq_interrupt(int irq, void *cookie) -{ - struct sparc64_msiq_cookie *msiq_cookie = cookie; - struct pci_pbm_info *pbm = msiq_cookie->pbm; - unsigned long msiqid = msiq_cookie->msiqid; - const struct sparc64_msiq_ops *ops; - unsigned long orig_head, head; - int err; - - ops = pbm->msi_ops; - - err = ops->get_head(pbm, msiqid, &head); - if (unlikely(err < 0)) - goto err_get_head; - - orig_head = head; - for (;;) { - unsigned long msi; - - err = ops->dequeue_msi(pbm, msiqid, &head, &msi); - if (likely(err > 0)) - __do_IRQ(pbm->msi_irq_table[msi - pbm->msi_first]); - - if (unlikely(err < 0)) - goto err_dequeue; - - if (err == 0) - break; - } - if (likely(head != orig_head)) { - err = ops->set_head(pbm, msiqid, head); - if (unlikely(err < 0)) - goto err_set_head; - } - return IRQ_HANDLED; - -err_get_head: - printk(KERN_EMERG "MSI: Get head on msiqid[%lu] gives error %d\n", - msiqid, err); - goto err_out; - -err_dequeue: - printk(KERN_EMERG "MSI: Dequeue head[%lu] from msiqid[%lu] " - "gives error %d\n", - head, msiqid, err); - goto err_out; - -err_set_head: - printk(KERN_EMERG "MSI: Set head[%lu] on msiqid[%lu] " - "gives error %d\n", - head, msiqid, err); - goto err_out; - -err_out: - return IRQ_NONE; -} - -static u32 pick_msiq(struct pci_pbm_info *pbm) -{ - static DEFINE_SPINLOCK(rotor_lock); - unsigned long flags; - u32 ret, rotor; - - spin_lock_irqsave(&rotor_lock, flags); - - rotor = pbm->msiq_rotor; - ret = pbm->msiq_first + rotor; - - if (++rotor >= pbm->msiq_num) - rotor = 0; - pbm->msiq_rotor = rotor; - - spin_unlock_irqrestore(&rotor_lock, flags); - - return ret; -} - - -static int alloc_msi(struct pci_pbm_info *pbm) -{ - int i; - - for (i = 0; i < pbm->msi_num; i++) { - if (!test_and_set_bit(i, pbm->msi_bitmap)) - return i + pbm->msi_first; - } - - return -ENOENT; -} - -static void free_msi(struct pci_pbm_info *pbm, int msi_num) -{ - msi_num -= pbm->msi_first; - clear_bit(msi_num, pbm->msi_bitmap); -} - -static struct irq_chip msi_irq = { - .typename = "PCI-MSI", - .mask = mask_msi_irq, - .unmask = unmask_msi_irq, - .enable = unmask_msi_irq, - .disable = mask_msi_irq, - /* XXX affinity XXX */ -}; - -int sparc64_setup_msi_irq(unsigned int *virt_irq_p, - struct pci_dev *pdev, - struct msi_desc *entry) -{ - struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; - const struct sparc64_msiq_ops *ops = pbm->msi_ops; - struct msi_msg msg; - int msi, err; - u32 msiqid; - - *virt_irq_p = virt_irq_alloc(0, 0); - err = -ENOMEM; - if (!*virt_irq_p) - goto out_err; - - set_irq_chip(*virt_irq_p, &msi_irq); - - err = alloc_msi(pbm); - if (unlikely(err < 0)) - goto out_virt_irq_free; - - msi = err; - - msiqid = pick_msiq(pbm); - - err = ops->msi_setup(pbm, msiqid, msi, - (entry->msi_attrib.is_64 ? 1 : 0)); - if (err) - goto out_msi_free; - - pbm->msi_irq_table[msi - pbm->msi_first] = *virt_irq_p; - - if (entry->msi_attrib.is_64) { - msg.address_hi = pbm->msi64_start >> 32; - msg.address_lo = pbm->msi64_start & 0xffffffff; - } else { - msg.address_hi = 0; - msg.address_lo = pbm->msi32_start; - } - msg.data = msi; - - set_irq_msi(*virt_irq_p, entry); - write_msi_msg(*virt_irq_p, &msg); - - return 0; - -out_msi_free: - free_msi(pbm, msi); - -out_virt_irq_free: - set_irq_chip(*virt_irq_p, NULL); - virt_irq_free(*virt_irq_p); - *virt_irq_p = 0; - -out_err: - return err; -} - -void sparc64_teardown_msi_irq(unsigned int virt_irq, - struct pci_dev *pdev) -{ - struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; - const struct sparc64_msiq_ops *ops = pbm->msi_ops; - unsigned int msi_num; - int i, err; - - for (i = 0; i < pbm->msi_num; i++) { - if (pbm->msi_irq_table[i] == virt_irq) - break; - } - if (i >= pbm->msi_num) { - printk(KERN_ERR "%s: teardown: No MSI for irq %u\n", - pbm->name, virt_irq); - return; - } - - msi_num = pbm->msi_first + i; - pbm->msi_irq_table[i] = ~0U; - - err = ops->msi_teardown(pbm, msi_num); - if (err) { - printk(KERN_ERR "%s: teardown: ops->teardown() on MSI %u, " - "irq %u, gives error %d\n", - pbm->name, msi_num, virt_irq, err); - return; - } - - free_msi(pbm, msi_num); - - set_irq_chip(virt_irq, NULL); - virt_irq_free(virt_irq); -} - -static int msi_bitmap_alloc(struct pci_pbm_info *pbm) -{ - unsigned long size, bits_per_ulong; - - bits_per_ulong = sizeof(unsigned long) * 8; - size = (pbm->msi_num + (bits_per_ulong - 1)) & ~(bits_per_ulong - 1); - size /= 8; - BUG_ON(size % sizeof(unsigned long)); - - pbm->msi_bitmap = kzalloc(size, GFP_KERNEL); - if (!pbm->msi_bitmap) - return -ENOMEM; - - return 0; -} - -static void msi_bitmap_free(struct pci_pbm_info *pbm) -{ - kfree(pbm->msi_bitmap); - pbm->msi_bitmap = NULL; -} - -static int msi_table_alloc(struct pci_pbm_info *pbm) -{ - int size, i; - - size = pbm->msiq_num * sizeof(struct sparc64_msiq_cookie); - pbm->msiq_irq_cookies = kzalloc(size, GFP_KERNEL); - if (!pbm->msiq_irq_cookies) - return -ENOMEM; - - for (i = 0; i < pbm->msiq_num; i++) { - struct sparc64_msiq_cookie *p; - - p = &pbm->msiq_irq_cookies[i]; - p->pbm = pbm; - p->msiqid = pbm->msiq_first + i; - } - - size = pbm->msi_num * sizeof(unsigned int); - pbm->msi_irq_table = kzalloc(size, GFP_KERNEL); - if (!pbm->msi_irq_table) { - kfree(pbm->msiq_irq_cookies); - pbm->msiq_irq_cookies = NULL; - return -ENOMEM; - } - - return 0; -} - -static void msi_table_free(struct pci_pbm_info *pbm) -{ - kfree(pbm->msiq_irq_cookies); - pbm->msiq_irq_cookies = NULL; - - kfree(pbm->msi_irq_table); - pbm->msi_irq_table = NULL; -} - -static int bringup_one_msi_queue(struct pci_pbm_info *pbm, - const struct sparc64_msiq_ops *ops, - unsigned long msiqid, - unsigned long devino) -{ - int irq = ops->msiq_build_irq(pbm, msiqid, devino); - int err; - - if (irq < 0) - return irq; - - err = request_irq(irq, sparc64_msiq_interrupt, 0, - "MSIQ", - &pbm->msiq_irq_cookies[msiqid - pbm->msiq_first]); - if (err) - return err; - - return 0; -} - -static int sparc64_bringup_msi_queues(struct pci_pbm_info *pbm, - const struct sparc64_msiq_ops *ops) -{ - int i; - - for (i = 0; i < pbm->msiq_num; i++) { - unsigned long msiqid = i + pbm->msiq_first; - unsigned long devino = i + pbm->msiq_first_devino; - int err; - - err = bringup_one_msi_queue(pbm, ops, msiqid, devino); - if (err) - return err; - } - - return 0; -} - -void sparc64_pbm_msi_init(struct pci_pbm_info *pbm, - const struct sparc64_msiq_ops *ops) -{ - const u32 *val; - int len; - - val = of_get_property(pbm->prom_node, "#msi-eqs", &len); - if (!val || len != 4) - goto no_msi; - pbm->msiq_num = *val; - if (pbm->msiq_num) { - const struct msiq_prop { - u32 first_msiq; - u32 num_msiq; - u32 first_devino; - } *mqp; - const struct msi_range_prop { - u32 first_msi; - u32 num_msi; - } *mrng; - const struct addr_range_prop { - u32 msi32_high; - u32 msi32_low; - u32 msi32_len; - u32 msi64_high; - u32 msi64_low; - u32 msi64_len; - } *arng; - - val = of_get_property(pbm->prom_node, "msi-eq-size", &len); - if (!val || len != 4) - goto no_msi; - - pbm->msiq_ent_count = *val; - - mqp = of_get_property(pbm->prom_node, - "msi-eq-to-devino", &len); - if (!mqp) - mqp = of_get_property(pbm->prom_node, - "msi-eq-devino", &len); - if (!mqp || len != sizeof(struct msiq_prop)) - goto no_msi; - - pbm->msiq_first = mqp->first_msiq; - pbm->msiq_first_devino = mqp->first_devino; - - val = of_get_property(pbm->prom_node, "#msi", &len); - if (!val || len != 4) - goto no_msi; - pbm->msi_num = *val; - - mrng = of_get_property(pbm->prom_node, "msi-ranges", &len); - if (!mrng || len != sizeof(struct msi_range_prop)) - goto no_msi; - pbm->msi_first = mrng->first_msi; - - val = of_get_property(pbm->prom_node, "msi-data-mask", &len); - if (!val || len != 4) - goto no_msi; - pbm->msi_data_mask = *val; - - val = of_get_property(pbm->prom_node, "msix-data-width", &len); - if (!val || len != 4) - goto no_msi; - pbm->msix_data_width = *val; - - arng = of_get_property(pbm->prom_node, "msi-address-ranges", - &len); - if (!arng || len != sizeof(struct addr_range_prop)) - goto no_msi; - pbm->msi32_start = ((u64)arng->msi32_high << 32) | - (u64) arng->msi32_low; - pbm->msi64_start = ((u64)arng->msi64_high << 32) | - (u64) arng->msi64_low; - pbm->msi32_len = arng->msi32_len; - pbm->msi64_len = arng->msi64_len; - - if (msi_bitmap_alloc(pbm)) - goto no_msi; - - if (msi_table_alloc(pbm)) { - msi_bitmap_free(pbm); - goto no_msi; - } - - if (ops->msiq_alloc(pbm)) { - msi_table_free(pbm); - msi_bitmap_free(pbm); - goto no_msi; - } - - if (sparc64_bringup_msi_queues(pbm, ops)) { - ops->msiq_free(pbm); - msi_table_free(pbm); - msi_bitmap_free(pbm); - goto no_msi; - } - - printk(KERN_INFO "%s: MSI Queue first[%u] num[%u] count[%u] " - "devino[0x%x]\n", - pbm->name, - pbm->msiq_first, pbm->msiq_num, - pbm->msiq_ent_count, - pbm->msiq_first_devino); - printk(KERN_INFO "%s: MSI first[%u] num[%u] mask[0x%x] " - "width[%u]\n", - pbm->name, - pbm->msi_first, pbm->msi_num, pbm->msi_data_mask, - pbm->msix_data_width); - printk(KERN_INFO "%s: MSI addr32[0x%lx:0x%x] " - "addr64[0x%lx:0x%x]\n", - pbm->name, - pbm->msi32_start, pbm->msi32_len, - pbm->msi64_start, pbm->msi64_len); - printk(KERN_INFO "%s: MSI queues at RA [%016lx]\n", - pbm->name, - __pa(pbm->msi_queues)); - - pbm->msi_ops = ops; - pbm->setup_msi_irq = sparc64_setup_msi_irq; - pbm->teardown_msi_irq = sparc64_teardown_msi_irq; - } - return; - -no_msi: - pbm->msiq_num = 0; - printk(KERN_INFO "%s: No MSI support.\n", pbm->name); -} diff --git a/trunk/arch/sparc64/kernel/pci_psycho.c b/trunk/arch/sparc64/kernel/pci_psycho.c index d27ee5d528a2..b6b4cfea5b5f 100644 --- a/trunk/arch/sparc64/kernel/pci_psycho.c +++ b/trunk/arch/sparc64/kernel/pci_psycho.c @@ -1058,6 +1058,12 @@ void psycho_init(struct device_node *dp, char *model_name) p->pbm_A.config_space = p->pbm_B.config_space = (pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE); + /* + * Psycho's PCI MEM space is mapped to a 2GB aligned area, so + * we need to adjust our MEM space mask. + */ + pci_memspace_mask = 0x7fffffffUL; + psycho_controller_hwinit(&p->pbm_A); if (psycho_iommu_init(&p->pbm_A)) diff --git a/trunk/arch/sparc64/kernel/pci_schizo.c b/trunk/arch/sparc64/kernel/pci_schizo.c index 9546ba9f5dee..3c30bfa1f3a3 100644 --- a/trunk/arch/sparc64/kernel/pci_schizo.c +++ b/trunk/arch/sparc64/kernel/pci_schizo.c @@ -1464,6 +1464,9 @@ static void __schizo_init(struct device_node *dp, char *model_name, int chip_typ p->pbm_B.iommu = iommu; + /* Like PSYCHO we have a 2GB aligned area for memory space. */ + pci_memspace_mask = 0x7fffffffUL; + if (schizo_pbm_init(p, dp, portid, chip_type)) goto fatal_memory_error; diff --git a/trunk/arch/sparc64/kernel/pci_sun4v.c b/trunk/arch/sparc64/kernel/pci_sun4v.c index 95de1444ee67..da724b13e89e 100644 --- a/trunk/arch/sparc64/kernel/pci_sun4v.c +++ b/trunk/arch/sparc64/kernel/pci_sun4v.c @@ -748,102 +748,111 @@ struct pci_sun4v_msiq_entry { u64 reserved2; }; -static int pci_sun4v_get_head(struct pci_pbm_info *pbm, unsigned long msiqid, - unsigned long *head) -{ - unsigned long err, limit; - - err = pci_sun4v_msiq_gethead(pbm->devhandle, msiqid, head); - if (unlikely(err)) - return -ENXIO; - - limit = pbm->msiq_ent_count * sizeof(struct pci_sun4v_msiq_entry); - if (unlikely(*head >= limit)) - return -EFBIG; - - return 0; -} - -static int pci_sun4v_dequeue_msi(struct pci_pbm_info *pbm, - unsigned long msiqid, unsigned long *head, - unsigned long *msi) +/* For now this just runs as a pre-handler for the real interrupt handler. + * So we just walk through the queue and ACK all the entries, update the + * head pointer, and return. + * + * In the longer term it would be nice to do something more integrated + * wherein we can pass in some of this MSI info to the drivers. This + * would be most useful for PCIe fabric error messages, although we could + * invoke those directly from the loop here in order to pass the info around. + */ +static void pci_sun4v_msi_prehandler(unsigned int ino, void *data1, void *data2) { - struct pci_sun4v_msiq_entry *ep; - unsigned long err, type; + struct pci_pbm_info *pbm = data1; + struct pci_sun4v_msiq_entry *base, *ep; + unsigned long msiqid, orig_head, head, type, err; - /* Note: void pointer arithmetic, 'head' is a byte offset */ - ep = (pbm->msi_queues + ((msiqid - pbm->msiq_first) * - (pbm->msiq_ent_count * - sizeof(struct pci_sun4v_msiq_entry))) + - *head); + msiqid = (unsigned long) data2; - if ((ep->version_type & MSIQ_TYPE_MASK) == 0) - return 0; + head = 0xdeadbeef; + err = pci_sun4v_msiq_gethead(pbm->devhandle, msiqid, &head); + if (unlikely(err)) + goto hv_error_get; + + if (unlikely(head >= (pbm->msiq_ent_count * sizeof(struct pci_sun4v_msiq_entry)))) + goto bad_offset; + + head /= sizeof(struct pci_sun4v_msiq_entry); + orig_head = head; + base = (pbm->msi_queues + ((msiqid - pbm->msiq_first) * + (pbm->msiq_ent_count * + sizeof(struct pci_sun4v_msiq_entry)))); + ep = &base[head]; + while ((ep->version_type & MSIQ_TYPE_MASK) != 0) { + type = (ep->version_type & MSIQ_TYPE_MASK) >> MSIQ_TYPE_SHIFT; + if (unlikely(type != MSIQ_TYPE_MSI32 && + type != MSIQ_TYPE_MSI64)) + goto bad_type; + + pci_sun4v_msi_setstate(pbm->devhandle, + ep->msi_data /* msi_num */, + HV_MSISTATE_IDLE); + + /* Clear the entry. */ + ep->version_type &= ~MSIQ_TYPE_MASK; + + /* Go to next entry in ring. */ + head++; + if (head >= pbm->msiq_ent_count) + head = 0; + ep = &base[head]; + } - type = (ep->version_type & MSIQ_TYPE_MASK) >> MSIQ_TYPE_SHIFT; - if (unlikely(type != MSIQ_TYPE_MSI32 && - type != MSIQ_TYPE_MSI64)) - return -EINVAL; + if (likely(head != orig_head)) { + /* ACK entries by updating head pointer. */ + head *= sizeof(struct pci_sun4v_msiq_entry); + err = pci_sun4v_msiq_sethead(pbm->devhandle, msiqid, head); + if (unlikely(err)) + goto hv_error_set; + } + return; - *msi = ep->msi_data; +hv_error_set: + printk(KERN_EMERG "MSI: Hypervisor set head gives error %lu\n", err); + goto hv_error_cont; - err = pci_sun4v_msi_setstate(pbm->devhandle, - ep->msi_data /* msi_num */, - HV_MSISTATE_IDLE); - if (unlikely(err)) - return -ENXIO; +hv_error_get: + printk(KERN_EMERG "MSI: Hypervisor get head gives error %lu\n", err); - /* Clear the entry. */ - ep->version_type &= ~MSIQ_TYPE_MASK; +hv_error_cont: + printk(KERN_EMERG "MSI: devhandle[%x] msiqid[%lx] head[%lu]\n", + pbm->devhandle, msiqid, head); + return; - (*head) += sizeof(struct pci_sun4v_msiq_entry); - if (*head >= - (pbm->msiq_ent_count * sizeof(struct pci_sun4v_msiq_entry))) - *head = 0; +bad_offset: + printk(KERN_EMERG "MSI: Hypervisor gives bad offset %lx max(%lx)\n", + head, pbm->msiq_ent_count * sizeof(struct pci_sun4v_msiq_entry)); + return; - return 1; +bad_type: + printk(KERN_EMERG "MSI: Entry has bad type %lx\n", type); + return; } -static int pci_sun4v_set_head(struct pci_pbm_info *pbm, unsigned long msiqid, - unsigned long head) +static int msi_bitmap_alloc(struct pci_pbm_info *pbm) { - unsigned long err; + unsigned long size, bits_per_ulong; - err = pci_sun4v_msiq_sethead(pbm->devhandle, msiqid, head); - if (unlikely(err)) - return -EINVAL; + bits_per_ulong = sizeof(unsigned long) * 8; + size = (pbm->msi_num + (bits_per_ulong - 1)) & ~(bits_per_ulong - 1); + size /= 8; + BUG_ON(size % sizeof(unsigned long)); - return 0; -} + pbm->msi_bitmap = kzalloc(size, GFP_KERNEL); + if (!pbm->msi_bitmap) + return -ENOMEM; -static int pci_sun4v_msi_setup(struct pci_pbm_info *pbm, unsigned long msiqid, - unsigned long msi, int is_msi64) -{ - if (pci_sun4v_msi_setmsiq(pbm->devhandle, msi, msiqid, - (is_msi64 ? - HV_MSITYPE_MSI64 : HV_MSITYPE_MSI32))) - return -ENXIO; - if (pci_sun4v_msi_setstate(pbm->devhandle, msi, HV_MSISTATE_IDLE)) - return -ENXIO; - if (pci_sun4v_msi_setvalid(pbm->devhandle, msi, HV_MSIVALID_VALID)) - return -ENXIO; return 0; } -static int pci_sun4v_msi_teardown(struct pci_pbm_info *pbm, unsigned long msi) +static void msi_bitmap_free(struct pci_pbm_info *pbm) { - unsigned long err, msiqid; - - err = pci_sun4v_msi_getmsiq(pbm->devhandle, msi, &msiqid); - if (err) - return -ENXIO; - - pci_sun4v_msi_setvalid(pbm->devhandle, msi, HV_MSIVALID_INVALID); - - return 0; + kfree(pbm->msi_bitmap); + pbm->msi_bitmap = NULL; } -static int pci_sun4v_msiq_alloc(struct pci_pbm_info *pbm) +static int msi_queue_alloc(struct pci_pbm_info *pbm) { unsigned long q_size, alloc_size, pages, order; int i; @@ -897,59 +906,232 @@ static int pci_sun4v_msiq_alloc(struct pci_pbm_info *pbm) return -EINVAL; } -static void pci_sun4v_msiq_free(struct pci_pbm_info *pbm) + +static int alloc_msi(struct pci_pbm_info *pbm) { - unsigned long q_size, alloc_size, pages, order; int i; - for (i = 0; i < pbm->msiq_num; i++) { - unsigned long msiqid = pbm->msiq_first + i; - - (void) pci_sun4v_msiq_conf(pbm->devhandle, msiqid, 0UL, 0); + for (i = 0; i < pbm->msi_num; i++) { + if (!test_and_set_bit(i, pbm->msi_bitmap)) + return i + pbm->msi_first; } - q_size = pbm->msiq_ent_count * sizeof(struct pci_sun4v_msiq_entry); - alloc_size = (pbm->msiq_num * q_size); - order = get_order(alloc_size); - - pages = (unsigned long) pbm->msi_queues; - - free_pages(pages, order); + return -ENOENT; +} - pbm->msi_queues = NULL; +static void free_msi(struct pci_pbm_info *pbm, int msi_num) +{ + msi_num -= pbm->msi_first; + clear_bit(msi_num, pbm->msi_bitmap); } -static int pci_sun4v_msiq_build_irq(struct pci_pbm_info *pbm, - unsigned long msiqid, - unsigned long devino) +static int pci_sun4v_setup_msi_irq(unsigned int *virt_irq_p, + struct pci_dev *pdev, + struct msi_desc *entry) { - unsigned int virt_irq = sun4v_build_irq(pbm->devhandle, devino); + struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; + unsigned long devino, msiqid; + struct msi_msg msg; + int msi_num, err; - if (!virt_irq) - return -ENOMEM; + *virt_irq_p = 0; + + msi_num = alloc_msi(pbm); + if (msi_num < 0) + return msi_num; + + err = sun4v_build_msi(pbm->devhandle, virt_irq_p, + pbm->msiq_first_devino, + (pbm->msiq_first_devino + + pbm->msiq_num)); + if (err < 0) + goto out_err; + devino = err; + msiqid = ((devino - pbm->msiq_first_devino) + + pbm->msiq_first); + + err = -EINVAL; if (pci_sun4v_msiq_setstate(pbm->devhandle, msiqid, HV_MSIQSTATE_IDLE)) - return -EINVAL; + if (err) + goto out_err; + if (pci_sun4v_msiq_setvalid(pbm->devhandle, msiqid, HV_MSIQ_VALID)) - return -EINVAL; + goto out_err; + + if (pci_sun4v_msi_setmsiq(pbm->devhandle, + msi_num, msiqid, + (entry->msi_attrib.is_64 ? + HV_MSITYPE_MSI64 : HV_MSITYPE_MSI32))) + goto out_err; + + if (pci_sun4v_msi_setstate(pbm->devhandle, msi_num, HV_MSISTATE_IDLE)) + goto out_err; + + if (pci_sun4v_msi_setvalid(pbm->devhandle, msi_num, HV_MSIVALID_VALID)) + goto out_err; + + sparc64_set_msi(*virt_irq_p, msi_num); + + if (entry->msi_attrib.is_64) { + msg.address_hi = pbm->msi64_start >> 32; + msg.address_lo = pbm->msi64_start & 0xffffffff; + } else { + msg.address_hi = 0; + msg.address_lo = pbm->msi32_start; + } + msg.data = msi_num; + + set_irq_msi(*virt_irq_p, entry); + write_msi_msg(*virt_irq_p, &msg); + + irq_install_pre_handler(*virt_irq_p, + pci_sun4v_msi_prehandler, + pbm, (void *) msiqid); + + return 0; + +out_err: + free_msi(pbm, msi_num); + return err; - return virt_irq; } -static const struct sparc64_msiq_ops pci_sun4v_msiq_ops = { - .get_head = pci_sun4v_get_head, - .dequeue_msi = pci_sun4v_dequeue_msi, - .set_head = pci_sun4v_set_head, - .msi_setup = pci_sun4v_msi_setup, - .msi_teardown = pci_sun4v_msi_teardown, - .msiq_alloc = pci_sun4v_msiq_alloc, - .msiq_free = pci_sun4v_msiq_free, - .msiq_build_irq = pci_sun4v_msiq_build_irq, -}; +static void pci_sun4v_teardown_msi_irq(unsigned int virt_irq, + struct pci_dev *pdev) +{ + struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; + unsigned long msiqid, err; + unsigned int msi_num; + + msi_num = sparc64_get_msi(virt_irq); + err = pci_sun4v_msi_getmsiq(pbm->devhandle, msi_num, &msiqid); + if (err) { + printk(KERN_ERR "%s: getmsiq gives error %lu\n", + pbm->name, err); + return; + } + + pci_sun4v_msi_setvalid(pbm->devhandle, msi_num, HV_MSIVALID_INVALID); + pci_sun4v_msiq_setvalid(pbm->devhandle, msiqid, HV_MSIQ_INVALID); + + free_msi(pbm, msi_num); + + /* The sun4v_destroy_msi() will liberate the devino and thus the MSIQ + * allocation. + */ + sun4v_destroy_msi(virt_irq); +} static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) { - sparc64_pbm_msi_init(pbm, &pci_sun4v_msiq_ops); + const u32 *val; + int len; + + val = of_get_property(pbm->prom_node, "#msi-eqs", &len); + if (!val || len != 4) + goto no_msi; + pbm->msiq_num = *val; + if (pbm->msiq_num) { + const struct msiq_prop { + u32 first_msiq; + u32 num_msiq; + u32 first_devino; + } *mqp; + const struct msi_range_prop { + u32 first_msi; + u32 num_msi; + } *mrng; + const struct addr_range_prop { + u32 msi32_high; + u32 msi32_low; + u32 msi32_len; + u32 msi64_high; + u32 msi64_low; + u32 msi64_len; + } *arng; + + val = of_get_property(pbm->prom_node, "msi-eq-size", &len); + if (!val || len != 4) + goto no_msi; + + pbm->msiq_ent_count = *val; + + mqp = of_get_property(pbm->prom_node, + "msi-eq-to-devino", &len); + if (!mqp || len != sizeof(struct msiq_prop)) + goto no_msi; + + pbm->msiq_first = mqp->first_msiq; + pbm->msiq_first_devino = mqp->first_devino; + + val = of_get_property(pbm->prom_node, "#msi", &len); + if (!val || len != 4) + goto no_msi; + pbm->msi_num = *val; + + mrng = of_get_property(pbm->prom_node, "msi-ranges", &len); + if (!mrng || len != sizeof(struct msi_range_prop)) + goto no_msi; + pbm->msi_first = mrng->first_msi; + + val = of_get_property(pbm->prom_node, "msi-data-mask", &len); + if (!val || len != 4) + goto no_msi; + pbm->msi_data_mask = *val; + + val = of_get_property(pbm->prom_node, "msix-data-width", &len); + if (!val || len != 4) + goto no_msi; + pbm->msix_data_width = *val; + + arng = of_get_property(pbm->prom_node, "msi-address-ranges", + &len); + if (!arng || len != sizeof(struct addr_range_prop)) + goto no_msi; + pbm->msi32_start = ((u64)arng->msi32_high << 32) | + (u64) arng->msi32_low; + pbm->msi64_start = ((u64)arng->msi64_high << 32) | + (u64) arng->msi64_low; + pbm->msi32_len = arng->msi32_len; + pbm->msi64_len = arng->msi64_len; + + if (msi_bitmap_alloc(pbm)) + goto no_msi; + + if (msi_queue_alloc(pbm)) { + msi_bitmap_free(pbm); + goto no_msi; + } + + printk(KERN_INFO "%s: MSI Queue first[%u] num[%u] count[%u] " + "devino[0x%x]\n", + pbm->name, + pbm->msiq_first, pbm->msiq_num, + pbm->msiq_ent_count, + pbm->msiq_first_devino); + printk(KERN_INFO "%s: MSI first[%u] num[%u] mask[0x%x] " + "width[%u]\n", + pbm->name, + pbm->msi_first, pbm->msi_num, pbm->msi_data_mask, + pbm->msix_data_width); + printk(KERN_INFO "%s: MSI addr32[0x%lx:0x%x] " + "addr64[0x%lx:0x%x]\n", + pbm->name, + pbm->msi32_start, pbm->msi32_len, + pbm->msi64_start, pbm->msi64_len); + printk(KERN_INFO "%s: MSI queues at RA [%p]\n", + pbm->name, + pbm->msi_queues); + } + pbm->setup_msi_irq = pci_sun4v_setup_msi_irq; + pbm->teardown_msi_irq = pci_sun4v_teardown_msi_irq; + + return; + +no_msi: + pbm->msiq_num = 0; + printk(KERN_INFO "%s: No MSI support.\n", pbm->name); } #else /* CONFIG_PCI_MSI */ static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) @@ -1055,6 +1237,11 @@ void __init sun4v_pci_init(struct device_node *dp, char *model_name) p->pbm_B.iommu = iommu; + /* Like PSYCHO and SCHIZO we have a 2GB aligned area + * for memory space. + */ + pci_memspace_mask = 0x7fffffffUL; + pci_sun4v_pbm_init(p, dp, devhandle); return; diff --git a/trunk/arch/sparc64/kernel/power.c b/trunk/arch/sparc64/kernel/power.c index 850cdffdd69c..881a09ee4c4c 100644 --- a/trunk/arch/sparc64/kernel/power.c +++ b/trunk/arch/sparc64/kernel/power.c @@ -105,11 +105,9 @@ static struct of_device_id power_match[] = { }; static struct of_platform_driver power_driver = { + .name = "power", .match_table = power_match, .probe = power_probe, - .driver = { - .name = "power", - }, }; void __init power_init(void) diff --git a/trunk/arch/sparc64/kernel/sun4v_ivec.S b/trunk/arch/sparc64/kernel/sun4v_ivec.S index e2f8e1b4882a..574bc248bca6 100644 --- a/trunk/arch/sparc64/kernel/sun4v_ivec.S +++ b/trunk/arch/sparc64/kernel/sun4v_ivec.S @@ -96,21 +96,19 @@ sun4v_dev_mondo: stxa %g2, [%g4] ASI_QUEUE membar #Sync - TRAP_LOAD_IRQ_WORK_PA(%g1, %g4) + /* Get &__irq_work[smp_processor_id()] into %g1. */ + TRAP_LOAD_IRQ_WORK(%g1, %g4) - /* For VIRQs, cookie is encoded as ~bucket_phys_addr */ - brlz,pt %g3, 1f - xnor %g3, %g0, %g4 - - /* Get __pa(&ivector_table[IVEC]) into %g4. */ - sethi %hi(ivector_table_pa), %g4 - ldx [%g4 + %lo(ivector_table_pa)], %g4 - sllx %g3, 4, %g3 + /* Get &ivector_table[IVEC] into %g4. */ + sethi %hi(ivector_table), %g4 + sllx %g3, 3, %g3 + or %g4, %lo(ivector_table), %g4 add %g4, %g3, %g4 -1: ldx [%g1], %g2 - stxa %g2, [%g4] ASI_PHYS_USE_EC - stx %g4, [%g1] + /* Insert ivector_table[] entry into __irq_work[] queue. */ + lduw [%g1], %g2 /* g2 = irq_work(cpu) */ + stw %g2, [%g4 + 0x00] /* bucket->irq_chain = g2 */ + stw %g4, [%g1] /* irq_work(cpu) = bucket */ /* Signal the interrupt by setting (1 << pil) in %softint. */ wr %g0, 1 << PIL_DEVICE_IRQ, %set_softint diff --git a/trunk/arch/sparc64/kernel/sys_sparc.c b/trunk/arch/sparc64/kernel/sys_sparc.c index 0d5c50264945..d108eeb0734f 100644 --- a/trunk/arch/sparc64/kernel/sys_sparc.c +++ b/trunk/arch/sparc64/kernel/sys_sparc.c @@ -436,7 +436,7 @@ asmlinkage long sparc_pipe(struct pt_regs *regs) asmlinkage long sys_ipc(unsigned int call, int first, unsigned long second, unsigned long third, void __user *ptr, long fifth) { - long err; + int err; /* No need for backward compatibility. We can start fresh... */ if (call <= SEMCTL) { @@ -453,9 +453,16 @@ asmlinkage long sys_ipc(unsigned int call, int first, unsigned long second, err = sys_semget(first, (int)second, (int)third); goto out; case SEMCTL: { - err = sys_semctl(first, third, - (int)second | IPC_64, - (union semun) ptr); + union semun fourth; + err = -EINVAL; + if (!ptr) + goto out; + err = -EFAULT; + if (get_user(fourth.__pad, + (void __user * __user *) ptr)) + goto out; + err = sys_semctl(first, (int)second | IPC_64, + (int)third, fourth); goto out; } default: diff --git a/trunk/arch/sparc64/kernel/time.c b/trunk/arch/sparc64/kernel/time.c index cd8c740cba1d..69cad1b653c1 100644 --- a/trunk/arch/sparc64/kernel/time.c +++ b/trunk/arch/sparc64/kernel/time.c @@ -764,11 +764,9 @@ static struct of_device_id clock_match[] = { }; static struct of_platform_driver clock_driver = { + .name = "clock", .match_table = clock_match, .probe = clock_probe, - .driver = { - .name = "clock", - }, }; static int __init clock_init(void) diff --git a/trunk/arch/sparc64/kernel/traps.c b/trunk/arch/sparc64/kernel/traps.c index 34573a55b6e5..6ef42b8e53d8 100644 --- a/trunk/arch/sparc64/kernel/traps.c +++ b/trunk/arch/sparc64/kernel/traps.c @@ -2569,8 +2569,8 @@ void __init trap_init(void) offsetof(struct trap_per_cpu, tsb_huge)) || (TRAP_PER_CPU_TSB_HUGE_TEMP != offsetof(struct trap_per_cpu, tsb_huge_temp)) || - (TRAP_PER_CPU_IRQ_WORKLIST_PA != - offsetof(struct trap_per_cpu, irq_worklist_pa)) || + (TRAP_PER_CPU_IRQ_WORKLIST != + offsetof(struct trap_per_cpu, irq_worklist)) || (TRAP_PER_CPU_CPU_MONDO_QMASK != offsetof(struct trap_per_cpu, cpu_mondo_qmask)) || (TRAP_PER_CPU_DEV_MONDO_QMASK != diff --git a/trunk/arch/sparc64/kernel/vmlinux.lds.S b/trunk/arch/sparc64/kernel/vmlinux.lds.S index 9fcd503bc04a..b982fa3dd748 100644 --- a/trunk/arch/sparc64/kernel/vmlinux.lds.S +++ b/trunk/arch/sparc64/kernel/vmlinux.lds.S @@ -10,138 +10,105 @@ ENTRY(_start) jiffies = jiffies_64; SECTIONS { - swapper_low_pmd_dir = 0x0000000000402000; - . = 0x4000; - .text 0x0000000000404000 : { - _text = .; - TEXT_TEXT - SCHED_TEXT - LOCK_TEXT - KPROBES_TEXT - *(.gnu.warning) - } = 0 - _etext = .; - PROVIDE (etext = .); + swapper_low_pmd_dir = 0x0000000000402000; + . = 0x4000; + .text 0x0000000000404000 : + { + _text = .; + TEXT_TEXT + SCHED_TEXT + LOCK_TEXT + KPROBES_TEXT + *(.gnu.warning) + } =0 + _etext = .; + PROVIDE (etext = .); - RO_DATA(PAGE_SIZE) - .data : { - DATA_DATA - CONSTRUCTORS - } - .data1 : { - *(.data1) - } - . = ALIGN(64); - .data.cacheline_aligned : { - *(.data.cacheline_aligned) - } - . = ALIGN(64); - .data.read_mostly : { - *(.data.read_mostly) - } - _edata = .; - PROVIDE (edata = .); - .fixup : { - *(.fixup) - } - . = ALIGN(16); - __ex_table : { - __start___ex_table = .; - *(__ex_table) - __stop___ex_table = .; - } - NOTES + RO_DATA(PAGE_SIZE) - . = ALIGN(PAGE_SIZE); - .init.text : { - __init_begin = .; - _sinittext = .; - *(.init.text) - _einittext = .; - } - .init.data : { - *(.init.data) - } - . = ALIGN(16); - .init.setup : { - __setup_start = .; - *(.init.setup) - __setup_end = .; - } - .initcall.init : { - __initcall_start = .; - INITCALLS - __initcall_end = .; - } - .con_initcall.init : { - __con_initcall_start = .; - *(.con_initcall.init) - __con_initcall_end = .; - } - SECURITY_INIT + .data : + { + DATA_DATA + CONSTRUCTORS + } + .data1 : { *(.data1) } + . = ALIGN(64); + .data.cacheline_aligned : { *(.data.cacheline_aligned) } + . = ALIGN(64); + .data.read_mostly : { *(.data.read_mostly) } + _edata = .; + PROVIDE (edata = .); + .fixup : { *(.fixup) } - . = ALIGN(4); - .tsb_ldquad_phys_patch : { - __tsb_ldquad_phys_patch = .; - *(.tsb_ldquad_phys_patch) - __tsb_ldquad_phys_patch_end = .; - } + . = ALIGN(16); + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; - .tsb_phys_patch : { - __tsb_phys_patch = .; - *(.tsb_phys_patch) - __tsb_phys_patch_end = .; - } + NOTES - .cpuid_patch : { - __cpuid_patch = .; - *(.cpuid_patch) - __cpuid_patch_end = .; - } - - .sun4v_1insn_patch : { - __sun4v_1insn_patch = .; - *(.sun4v_1insn_patch) - __sun4v_1insn_patch_end = .; - } - .sun4v_2insn_patch : { - __sun4v_2insn_patch = .; - *(.sun4v_2insn_patch) - __sun4v_2insn_patch_end = .; - } + . = ALIGN(PAGE_SIZE); + __init_begin = .; + .init.text : { + _sinittext = .; + *(.init.text) + _einittext = .; + } + .init.data : { *(.init.data) } + . = ALIGN(16); + __setup_start = .; + .init.setup : { *(.init.setup) } + __setup_end = .; + __initcall_start = .; + .initcall.init : { + INITCALLS + } + __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; + SECURITY_INIT + . = ALIGN(4); + __tsb_ldquad_phys_patch = .; + .tsb_ldquad_phys_patch : { *(.tsb_ldquad_phys_patch) } + __tsb_ldquad_phys_patch_end = .; + __tsb_phys_patch = .; + .tsb_phys_patch : { *(.tsb_phys_patch) } + __tsb_phys_patch_end = .; + __cpuid_patch = .; + .cpuid_patch : { *(.cpuid_patch) } + __cpuid_patch_end = .; + __sun4v_1insn_patch = .; + .sun4v_1insn_patch : { *(.sun4v_1insn_patch) } + __sun4v_1insn_patch_end = .; + __sun4v_2insn_patch = .; + .sun4v_2insn_patch : { *(.sun4v_2insn_patch) } + __sun4v_2insn_patch_end = .; #ifdef CONFIG_BLK_DEV_INITRD - . = ALIGN(PAGE_SIZE); - .init.ramfs : { - __initramfs_start = .; - *(.init.ramfs) - __initramfs_end = .; - } + . = ALIGN(PAGE_SIZE); + __initramfs_start = .; + .init.ramfs : { *(.init.ramfs) } + __initramfs_end = .; #endif - PERCPU(PAGE_SIZE) + PERCPU(PAGE_SIZE) - . = ALIGN(PAGE_SIZE); - __init_end = .; - __bss_start = .; - .sbss : { - *(.sbss) - *(.scommon) - } - .bss : { - *(.dynbss) - *(.bss) - *(COMMON) - } - _end = . ; - PROVIDE (end = .); + . = ALIGN(PAGE_SIZE); + __init_end = .; + __bss_start = .; + .sbss : { *(.sbss) *(.scommon) } + .bss : + { + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); + /DISCARD/ : { *(.exit.text) *(.exit.data) *(.exitcall.exit) } - /DISCARD/ : { - *(.exit.text) - *(.exit.data) - *(.exitcall.exit) - } + STABS_DEBUG - STABS_DEBUG - DWARF_DEBUG + DWARF_DEBUG } diff --git a/trunk/arch/sparc64/lib/xor.S b/trunk/arch/sparc64/lib/xor.S index f44f58f40234..a79c8888170d 100644 --- a/trunk/arch/sparc64/lib/xor.S +++ b/trunk/arch/sparc64/lib/xor.S @@ -491,12 +491,12 @@ xor_niagara_4: /* %o0=bytes, %o1=dest, %o2=src1, %o3=src2, %o4=src3 */ ldda [%i1 + 0x10] %asi, %i2 /* %i2/%i3 = src1 + 0x10 */ xor %g2, %i4, %g2 xor %g3, %i5, %g3 - ldda [%l7 + 0x10] %asi, %i4 /* %i4/%i5 = src2 + 0x10 */ + ldda [%i7 + 0x10] %asi, %i4 /* %i4/%i5 = src2 + 0x10 */ xor %l0, %g2, %l0 xor %l1, %g3, %l1 stxa %l0, [%i0 + 0x00] %asi stxa %l1, [%i0 + 0x08] %asi - ldda [%l6 + 0x10] %asi, %g2 /* %g2/%g3 = src3 + 0x10 */ + ldda [%i6 + 0x10] %asi, %g2 /* %g2/%g3 = src3 + 0x10 */ ldda [%i0 + 0x10] %asi, %l0 /* %l0/%l1 = dest + 0x10 */ xor %i4, %i2, %i4 @@ -504,12 +504,12 @@ xor_niagara_4: /* %o0=bytes, %o1=dest, %o2=src1, %o3=src2, %o4=src3 */ ldda [%i1 + 0x20] %asi, %i2 /* %i2/%i3 = src1 + 0x20 */ xor %g2, %i4, %g2 xor %g3, %i5, %g3 - ldda [%l7 + 0x20] %asi, %i4 /* %i4/%i5 = src2 + 0x20 */ + ldda [%i7 + 0x20] %asi, %i4 /* %i4/%i5 = src2 + 0x20 */ xor %l0, %g2, %l0 xor %l1, %g3, %l1 stxa %l0, [%i0 + 0x10] %asi stxa %l1, [%i0 + 0x18] %asi - ldda [%l6 + 0x20] %asi, %g2 /* %g2/%g3 = src3 + 0x20 */ + ldda [%i6 + 0x20] %asi, %g2 /* %g2/%g3 = src3 + 0x20 */ ldda [%i0 + 0x20] %asi, %l0 /* %l0/%l1 = dest + 0x20 */ xor %i4, %i2, %i4 @@ -517,12 +517,12 @@ xor_niagara_4: /* %o0=bytes, %o1=dest, %o2=src1, %o3=src2, %o4=src3 */ ldda [%i1 + 0x30] %asi, %i2 /* %i2/%i3 = src1 + 0x30 */ xor %g2, %i4, %g2 xor %g3, %i5, %g3 - ldda [%l7 + 0x30] %asi, %i4 /* %i4/%i5 = src2 + 0x30 */ + ldda [%i7 + 0x30] %asi, %i4 /* %i4/%i5 = src2 + 0x30 */ xor %l0, %g2, %l0 xor %l1, %g3, %l1 stxa %l0, [%i0 + 0x20] %asi stxa %l1, [%i0 + 0x28] %asi - ldda [%l6 + 0x30] %asi, %g2 /* %g2/%g3 = src3 + 0x30 */ + ldda [%i6 + 0x30] %asi, %g2 /* %g2/%g3 = src3 + 0x30 */ ldda [%i0 + 0x30] %asi, %l0 /* %l0/%l1 = dest + 0x30 */ prefetch [%i1 + 0x40], #one_read diff --git a/trunk/arch/sparc64/mm/init.c b/trunk/arch/sparc64/mm/init.c index f0ab9aab308f..3010227fe243 100644 --- a/trunk/arch/sparc64/mm/init.c +++ b/trunk/arch/sparc64/mm/init.c @@ -631,6 +631,7 @@ void prom_world(int enter) __asm__ __volatile__("flushw"); } +#ifdef DCACHE_ALIASING_POSSIBLE void __flush_dcache_range(unsigned long start, unsigned long end) { unsigned long va; @@ -654,6 +655,7 @@ void __flush_dcache_range(unsigned long start, unsigned long end) "i" (ASI_DCACHE_INVALIDATE)); } } +#endif /* DCACHE_ALIASING_POSSIBLE */ /* get_new_mmu_context() uses "cache + 1". */ DEFINE_SPINLOCK(ctx_alloc_lock); diff --git a/trunk/drivers/ata/pata_mpc52xx.c b/trunk/drivers/ata/pata_mpc52xx.c index 50c56e2814c1..412140f02853 100644 --- a/trunk/drivers/ata/pata_mpc52xx.c +++ b/trunk/drivers/ata/pata_mpc52xx.c @@ -308,6 +308,7 @@ mpc52xx_ata_init_one(struct device *dev, struct mpc52xx_ata_priv *priv, struct ata_host *host; struct ata_port *ap; struct ata_ioports *aio; + int rc; host = ata_host_alloc(dev, 1); if (!host) diff --git a/trunk/drivers/base/memory.c b/trunk/drivers/base/memory.c index 7a1390cd6aad..cb99daeae936 100644 --- a/trunk/drivers/base/memory.c +++ b/trunk/drivers/base/memory.c @@ -34,7 +34,7 @@ static const char *memory_uevent_name(struct kset *kset, struct kobject *kobj) return MEMORY_CLASS_NAME; } -static int memory_uevent(struct kset *kset, struct kobject *obj, struct kobj_uevent_env *env) +static int memory_uevent(struct kset *kset, struct kobj_uevent_env *env) { int retval = 0; diff --git a/trunk/drivers/mmc/core/sdio_bus.c b/trunk/drivers/mmc/core/sdio_bus.c index 233d0f9b3c4b..0713a8c71e54 100644 --- a/trunk/drivers/mmc/core/sdio_bus.c +++ b/trunk/drivers/mmc/core/sdio_bus.c @@ -96,23 +96,30 @@ static int sdio_bus_match(struct device *dev, struct device_driver *drv) } static int -sdio_bus_uevent(struct device *dev, struct kobj_uevent_env *env) +sdio_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf, + int buf_size) { struct sdio_func *func = dev_to_sdio_func(dev); + int i = 0, length = 0; - if (add_uevent_var(env, + if (add_uevent_var(envp, num_envp, &i, + buf, buf_size, &length, "SDIO_CLASS=%02X", func->class)) return -ENOMEM; - if (add_uevent_var(env, + if (add_uevent_var(envp, num_envp, &i, + buf, buf_size, &length, "SDIO_ID=%04X:%04X", func->vendor, func->device)) return -ENOMEM; - if (add_uevent_var(env, + if (add_uevent_var(envp, num_envp, &i, + buf, buf_size, &length, "MODALIAS=sdio:c%02Xv%04Xd%04X", func->class, func->vendor, func->device)) return -ENOMEM; + envp[i] = NULL; + return 0; } diff --git a/trunk/drivers/mtd/onenand/onenand_base.c b/trunk/drivers/mtd/onenand/onenand_base.c index b2c40f67db83..f633941011a5 100644 --- a/trunk/drivers/mtd/onenand/onenand_base.c +++ b/trunk/drivers/mtd/onenand/onenand_base.c @@ -1904,7 +1904,12 @@ static int onenand_do_lock_cmd(struct mtd_info *mtd, loff_t ofs, size_t len, int */ static int onenand_lock(struct mtd_info *mtd, loff_t ofs, size_t len) { - return onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_LOCK); + int ret; + + onenand_get_device(mtd, FL_LOCKING); + ret = onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_LOCK); + onenand_release_device(mtd); + return ret; } /** @@ -1917,7 +1922,12 @@ static int onenand_lock(struct mtd_info *mtd, loff_t ofs, size_t len) */ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) { - return onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK); + int ret; + + onenand_get_device(mtd, FL_LOCKING); + ret = onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK); + onenand_release_device(mtd); + return ret; } /** @@ -1979,7 +1989,7 @@ static int onenand_unlock_all(struct mtd_info *mtd) loff_t ofs = this->chipsize >> 1; size_t len = mtd->erasesize; - onenand_unlock(mtd, ofs, len); + onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK); } onenand_check_lock_status(this); @@ -1987,7 +1997,7 @@ static int onenand_unlock_all(struct mtd_info *mtd) return 0; } - onenand_unlock(mtd, 0x0, this->chipsize); + onenand_do_lock_cmd(mtd, 0x0, this->chipsize, ONENAND_CMD_UNLOCK); return 0; } diff --git a/trunk/drivers/net/ibm_newemac/rgmii.c b/trunk/drivers/net/ibm_newemac/rgmii.c index 3f57d6cd26e2..bcd7fc639c40 100644 --- a/trunk/drivers/net/ibm_newemac/rgmii.c +++ b/trunk/drivers/net/ibm_newemac/rgmii.c @@ -251,7 +251,7 @@ static int __devinit rgmii_probe(struct of_device *ofdev, } /* Check for RGMII type */ - if (of_device_is_compatible(ofdev->node, "ibm,rgmii-axon")) + if (device_is_compatible(ofdev->node, "ibm,rgmii-axon")) dev->type = RGMII_AXON; else dev->type = RGMII_STANDARD; diff --git a/trunk/drivers/serial/mpc52xx_uart.c b/trunk/drivers/serial/mpc52xx_uart.c index ec36ad78d2fe..035cca028199 100644 --- a/trunk/drivers/serial/mpc52xx_uart.c +++ b/trunk/drivers/serial/mpc52xx_uart.c @@ -756,8 +756,8 @@ mpc52xx_console_setup(struct console *co, char *options) if (port->membase == NULL) return -EINVAL; - pr_debug("mpc52xx-psc uart at %p, mapped to %p, irq=%x, freq=%i\n", - (void*)port->mapbase, port->membase, port->irq, port->uartclk); + pr_debug("mpc52xx-psc uart at %lx, mapped to %p, irq=%x, freq=%i\n", + port->mapbase, port->membase, port->irq, port->uartclk); /* Setup the port parameters accoding to options */ if (options) @@ -974,8 +974,8 @@ mpc52xx_uart_of_probe(struct of_device *op, const struct of_device_id *match) port->mapbase = res.start; port->irq = irq_of_parse_and_map(op->node, 0); - dev_dbg(&op->dev, "mpc52xx-psc uart at %p, irq=%x, freq=%i\n", - (void*)port->mapbase, port->irq, port->uartclk); + dev_dbg(&op->dev, "mpc52xx-psc uart at %lx, irq=%x, freq=%i\n", + port->mapbase, port->irq, port->uartclk); if ((port->irq==NO_IRQ) || !port->mapbase) { printk(KERN_ERR "Could not allocate resources for PSC\n"); diff --git a/trunk/drivers/ssb/main.c b/trunk/drivers/ssb/main.c index c12a741b5574..cfd13eb866b8 100644 --- a/trunk/drivers/ssb/main.c +++ b/trunk/drivers/ssb/main.c @@ -321,17 +321,23 @@ static int ssb_bus_match(struct device *dev, struct device_driver *drv) return 0; } -static int ssb_device_uevent(struct device *dev, struct kobj_uevent_env *env) +static int ssb_device_uevent(struct device *dev, char **envp, int num_envp, + char *buffer, int buffer_size) { struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); + int ret, i = 0, length = 0; if (!dev) return -ENODEV; - return add_uevent_var(env, + ret = add_uevent_var(envp, num_envp, &i, + buffer, buffer_size, &length, "MODALIAS=ssb:v%04Xid%04Xrev%02X", ssb_dev->id.vendor, ssb_dev->id.coreid, ssb_dev->id.revision); + envp[i] = NULL; + + return ret; } static struct bus_type ssb_bustype = { diff --git a/trunk/drivers/ssb/pcmcia.c b/trunk/drivers/ssb/pcmcia.c index b6abee846f02..7c773603b402 100644 --- a/trunk/drivers/ssb/pcmcia.c +++ b/trunk/drivers/ssb/pcmcia.c @@ -10,7 +10,6 @@ #include #include -#include #include #include diff --git a/trunk/drivers/usb/host/ohci-ssb.c b/trunk/drivers/usb/host/ohci-ssb.c index fe70e72340de..bc3e785d8c00 100644 --- a/trunk/drivers/usb/host/ohci-ssb.c +++ b/trunk/drivers/usb/host/ohci-ssb.c @@ -117,10 +117,8 @@ static const struct hc_driver ssb_ohci_hc_driver = { .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, .hub_irq_enable = ohci_rhsc_enable, -#ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, -#endif .start_port_reset = ohci_start_port_reset, }; diff --git a/trunk/drivers/video/cg6.c b/trunk/drivers/video/cg6.c index 549891d76ef5..ee9046db9c7d 100644 --- a/trunk/drivers/video/cg6.c +++ b/trunk/drivers/video/cg6.c @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -37,7 +38,6 @@ static void cg6_fillrect(struct fb_info *, const struct fb_fillrect *); static int cg6_sync(struct fb_info *); static int cg6_mmap(struct fb_info *, struct vm_area_struct *); static int cg6_ioctl(struct fb_info *, unsigned int, unsigned long); -static void cg6_copyarea(struct fb_info *info, const struct fb_copyarea *area); /* * Frame buffer operations @@ -48,7 +48,7 @@ static struct fb_ops cg6_ops = { .fb_setcolreg = cg6_setcolreg, .fb_blank = cg6_blank, .fb_fillrect = cg6_fillrect, - .fb_copyarea = cg6_copyarea, + .fb_copyarea = cfb_copyarea, .fb_imageblit = cg6_imageblit, .fb_sync = cg6_sync, .fb_mmap = cg6_mmap, @@ -65,41 +65,41 @@ static struct fb_ops cg6_ops = { * The FBC could be the frame buffer control * The FHC could is the frame buffer hardware control. */ -#define CG6_ROM_OFFSET 0x0UL -#define CG6_BROOKTREE_OFFSET 0x200000UL -#define CG6_DHC_OFFSET 0x240000UL -#define CG6_ALT_OFFSET 0x280000UL -#define CG6_FHC_OFFSET 0x300000UL -#define CG6_THC_OFFSET 0x301000UL -#define CG6_FBC_OFFSET 0x700000UL -#define CG6_TEC_OFFSET 0x701000UL -#define CG6_RAM_OFFSET 0x800000UL +#define CG6_ROM_OFFSET 0x0UL +#define CG6_BROOKTREE_OFFSET 0x200000UL +#define CG6_DHC_OFFSET 0x240000UL +#define CG6_ALT_OFFSET 0x280000UL +#define CG6_FHC_OFFSET 0x300000UL +#define CG6_THC_OFFSET 0x301000UL +#define CG6_FBC_OFFSET 0x700000UL +#define CG6_TEC_OFFSET 0x701000UL +#define CG6_RAM_OFFSET 0x800000UL /* FHC definitions */ -#define CG6_FHC_FBID_SHIFT 24 -#define CG6_FHC_FBID_MASK 255 -#define CG6_FHC_REV_SHIFT 20 -#define CG6_FHC_REV_MASK 15 -#define CG6_FHC_FROP_DISABLE (1 << 19) -#define CG6_FHC_ROW_DISABLE (1 << 18) -#define CG6_FHC_SRC_DISABLE (1 << 17) -#define CG6_FHC_DST_DISABLE (1 << 16) -#define CG6_FHC_RESET (1 << 15) -#define CG6_FHC_LITTLE_ENDIAN (1 << 13) -#define CG6_FHC_RES_MASK (3 << 11) -#define CG6_FHC_1024 (0 << 11) -#define CG6_FHC_1152 (1 << 11) -#define CG6_FHC_1280 (2 << 11) -#define CG6_FHC_1600 (3 << 11) -#define CG6_FHC_CPU_MASK (3 << 9) -#define CG6_FHC_CPU_SPARC (0 << 9) -#define CG6_FHC_CPU_68020 (1 << 9) -#define CG6_FHC_CPU_386 (2 << 9) -#define CG6_FHC_TEST (1 << 8) -#define CG6_FHC_TEST_X_SHIFT 4 -#define CG6_FHC_TEST_X_MASK 15 -#define CG6_FHC_TEST_Y_SHIFT 0 -#define CG6_FHC_TEST_Y_MASK 15 +#define CG6_FHC_FBID_SHIFT 24 +#define CG6_FHC_FBID_MASK 255 +#define CG6_FHC_REV_SHIFT 20 +#define CG6_FHC_REV_MASK 15 +#define CG6_FHC_FROP_DISABLE (1 << 19) +#define CG6_FHC_ROW_DISABLE (1 << 18) +#define CG6_FHC_SRC_DISABLE (1 << 17) +#define CG6_FHC_DST_DISABLE (1 << 16) +#define CG6_FHC_RESET (1 << 15) +#define CG6_FHC_LITTLE_ENDIAN (1 << 13) +#define CG6_FHC_RES_MASK (3 << 11) +#define CG6_FHC_1024 (0 << 11) +#define CG6_FHC_1152 (1 << 11) +#define CG6_FHC_1280 (2 << 11) +#define CG6_FHC_1600 (3 << 11) +#define CG6_FHC_CPU_MASK (3 << 9) +#define CG6_FHC_CPU_SPARC (0 << 9) +#define CG6_FHC_CPU_68020 (1 << 9) +#define CG6_FHC_CPU_386 (2 << 9) +#define CG6_FHC_TEST (1 << 8) +#define CG6_FHC_TEST_X_SHIFT 4 +#define CG6_FHC_TEST_X_MASK 15 +#define CG6_FHC_TEST_Y_SHIFT 0 +#define CG6_FHC_TEST_Y_MASK 15 /* FBC mode definitions */ #define CG6_FBC_BLIT_IGNORE 0x00000000 @@ -150,17 +150,17 @@ static struct fb_ops cg6_ops = { #define CG6_FBC_INDEX_MASK 0x00000030 /* THC definitions */ -#define CG6_THC_MISC_REV_SHIFT 16 -#define CG6_THC_MISC_REV_MASK 15 -#define CG6_THC_MISC_RESET (1 << 12) -#define CG6_THC_MISC_VIDEO (1 << 10) -#define CG6_THC_MISC_SYNC (1 << 9) -#define CG6_THC_MISC_VSYNC (1 << 8) -#define CG6_THC_MISC_SYNC_ENAB (1 << 7) -#define CG6_THC_MISC_CURS_RES (1 << 6) -#define CG6_THC_MISC_INT_ENAB (1 << 5) -#define CG6_THC_MISC_INT (1 << 4) -#define CG6_THC_MISC_INIT 0x9f +#define CG6_THC_MISC_REV_SHIFT 16 +#define CG6_THC_MISC_REV_MASK 15 +#define CG6_THC_MISC_RESET (1 << 12) +#define CG6_THC_MISC_VIDEO (1 << 10) +#define CG6_THC_MISC_SYNC (1 << 9) +#define CG6_THC_MISC_VSYNC (1 << 8) +#define CG6_THC_MISC_SYNC_ENAB (1 << 7) +#define CG6_THC_MISC_CURS_RES (1 << 6) +#define CG6_THC_MISC_INT_ENAB (1 << 5) +#define CG6_THC_MISC_INT (1 << 4) +#define CG6_THC_MISC_INIT 0x9f /* The contents are unknown */ struct cg6_tec { @@ -170,25 +170,25 @@ struct cg6_tec { }; struct cg6_thc { - u32 thc_pad0[512]; - u32 thc_hs; /* hsync timing */ - u32 thc_hsdvs; - u32 thc_hd; - u32 thc_vs; /* vsync timing */ - u32 thc_vd; - u32 thc_refresh; - u32 thc_misc; - u32 thc_pad1[56]; - u32 thc_cursxy; /* cursor x,y position (16 bits each) */ - u32 thc_cursmask[32]; /* cursor mask bits */ - u32 thc_cursbits[32]; /* what to show where mask enabled */ + u32 thc_pad0[512]; + u32 thc_hs; /* hsync timing */ + u32 thc_hsdvs; + u32 thc_hd; + u32 thc_vs; /* vsync timing */ + u32 thc_vd; + u32 thc_refresh; + u32 thc_misc; + u32 thc_pad1[56]; + u32 thc_cursxy; /* cursor x,y position (16 bits each) */ + u32 thc_cursmask[32]; /* cursor mask bits */ + u32 thc_cursbits[32]; /* what to show where mask enabled */ }; struct cg6_fbc { u32 xxx0[1]; u32 mode; u32 clip; - u32 xxx1[1]; + u32 xxx1[1]; u32 s; u32 draw; u32 blit; @@ -243,10 +243,10 @@ struct cg6_fbc { }; struct bt_regs { - u32 addr; - u32 color_map; - u32 control; - u32 cursor; + u32 addr; + u32 color_map; + u32 control; + u32 cursor; }; struct cg6_par { @@ -267,7 +267,7 @@ struct cg6_par { static int cg6_sync(struct fb_info *info) { - struct cg6_par *par = (struct cg6_par *)info->par; + struct cg6_par *par = (struct cg6_par *) info->par; struct cg6_fbc __iomem *fbc = par->fbc; int limit = 10000; @@ -281,24 +281,24 @@ static int cg6_sync(struct fb_info *info) } /** - * cg6_fillrect - Draws a rectangle on the screen. + * cg6_fillrect - REQUIRED function. Can use generic routines if + * non acclerated hardware and packed pixel based. + * Draws a rectangle on the screen. * - * @info: frame buffer structure that represents a single frame buffer - * @rect: structure defining the rectagle and operation. + * @info: frame buffer structure that represents a single frame buffer + * @rect: structure defining the rectagle and operation. */ static void cg6_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { - struct cg6_par *par = (struct cg6_par *)info->par; + struct cg6_par *par = (struct cg6_par *) info->par; struct cg6_fbc __iomem *fbc = par->fbc; unsigned long flags; s32 val; - /* CG6 doesn't handle ROP_XOR */ + /* XXX doesn't handle ROP_XOR */ spin_lock_irqsave(&par->lock, flags); - cg6_sync(info); - sbus_writel(rect->color, &fbc->fg); sbus_writel(~(u32)0, &fbc->pixelm); sbus_writel(0xea80ff00, &fbc->alu); @@ -316,56 +316,16 @@ static void cg6_fillrect(struct fb_info *info, const struct fb_fillrect *rect) } /** - * cg6_copyarea - Copies one area of the screen to another area. - * - * @info: frame buffer structure that represents a single frame buffer - * @area: Structure providing the data to copy the framebuffer contents - * from one region to another. - * - * This drawing operation copies a rectangular area from one area of the - * screen to another area. - */ -static void cg6_copyarea(struct fb_info *info, const struct fb_copyarea *area) -{ - struct cg6_par *par = (struct cg6_par *)info->par; - struct cg6_fbc __iomem *fbc = par->fbc; - unsigned long flags; - int i; - - spin_lock_irqsave(&par->lock, flags); - - cg6_sync(info); - - sbus_writel(0xff, &fbc->fg); - sbus_writel(0x00, &fbc->bg); - sbus_writel(~0, &fbc->pixelm); - sbus_writel(0xe880cccc, &fbc->alu); - sbus_writel(0, &fbc->s); - sbus_writel(0, &fbc->clip); - - sbus_writel(area->sy, &fbc->y0); - sbus_writel(area->sx, &fbc->x0); - sbus_writel(area->sy + area->height - 1, &fbc->y1); - sbus_writel(area->sx + area->width - 1, &fbc->x1); - sbus_writel(area->dy, &fbc->y2); - sbus_writel(area->dx, &fbc->x2); - sbus_writel(area->dy + area->height - 1, &fbc->y3); - sbus_writel(area->dx + area->width - 1, &fbc->x3); - do { - i = sbus_readl(&fbc->blit); - } while (i < 0 && (i & 0x20000000)); - spin_unlock_irqrestore(&par->lock, flags); -} - -/** - * cg6_imageblit - Copies a image from system memory to the screen. + * cg6_imageblit - REQUIRED function. Can use generic routines if + * non acclerated hardware and packed pixel based. + * Copies a image from system memory to the screen. * - * @info: frame buffer structure that represents a single frame buffer - * @image: structure defining the image. + * @info: frame buffer structure that represents a single frame buffer + * @image: structure defining the image. */ static void cg6_imageblit(struct fb_info *info, const struct fb_image *image) { - struct cg6_par *par = (struct cg6_par *)info->par; + struct cg6_par *par = (struct cg6_par *) info->par; struct cg6_fbc __iomem *fbc = par->fbc; const u8 *data = image->data; unsigned long flags; @@ -403,7 +363,7 @@ static void cg6_imageblit(struct fb_info *info, const struct fb_image *image) sbus_writel(y, &fbc->y0); sbus_writel(x, &fbc->x0); sbus_writel(x + 32 - 1, &fbc->x1); - + val = ((u32)data[0] << 24) | ((u32)data[1] << 16) | ((u32)data[2] << 8) | @@ -444,20 +404,19 @@ static void cg6_imageblit(struct fb_info *info, const struct fb_image *image) } /** - * cg6_setcolreg - Sets a color register. - * - * @regno: boolean, 0 copy local, 1 get_user() function - * @red: frame buffer colormap structure - * @green: The green value which can be up to 16 bits wide - * @blue: The blue value which can be up to 16 bits wide. - * @transp: If supported the alpha value which can be up to 16 bits wide. - * @info: frame buffer info structure + * cg6_setcolreg - Optional function. Sets a color register. + * @regno: boolean, 0 copy local, 1 get_user() function + * @red: frame buffer colormap structure + * @green: The green value which can be up to 16 bits wide + * @blue: The blue value which can be up to 16 bits wide. + * @transp: If supported the alpha value which can be up to 16 bits wide. + * @info: frame buffer info structure */ static int cg6_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *info) { - struct cg6_par *par = (struct cg6_par *)info->par; + struct cg6_par *par = (struct cg6_par *) info->par; struct bt_regs __iomem *bt = par->bt; unsigned long flags; @@ -481,24 +440,25 @@ static int cg6_setcolreg(unsigned regno, } /** - * cg6_blank - Blanks the display. - * - * @blank_mode: the blank mode we want. - * @info: frame buffer structure that represents a single frame buffer + * cg6_blank - Optional function. Blanks the display. + * @blank_mode: the blank mode we want. + * @info: frame buffer structure that represents a single frame buffer */ -static int cg6_blank(int blank, struct fb_info *info) +static int +cg6_blank(int blank, struct fb_info *info) { - struct cg6_par *par = (struct cg6_par *)info->par; + struct cg6_par *par = (struct cg6_par *) info->par; struct cg6_thc __iomem *thc = par->thc; unsigned long flags; u32 val; spin_lock_irqsave(&par->lock, flags); - val = sbus_readl(&thc->thc_misc); switch (blank) { case FB_BLANK_UNBLANK: /* Unblanking */ + val = sbus_readl(&thc->thc_misc); val |= CG6_THC_MISC_VIDEO; + sbus_writel(val, &thc->thc_misc); par->flags &= ~CG6_FLAG_BLANKED; break; @@ -506,12 +466,13 @@ static int cg6_blank(int blank, struct fb_info *info) case FB_BLANK_VSYNC_SUSPEND: /* VESA blank (vsync off) */ case FB_BLANK_HSYNC_SUSPEND: /* VESA blank (hsync off) */ case FB_BLANK_POWERDOWN: /* Poweroff */ + val = sbus_readl(&thc->thc_misc); val &= ~CG6_THC_MISC_VIDEO; + sbus_writel(val, &thc->thc_misc); par->flags |= CG6_FLAG_BLANKED; break; } - sbus_writel(val, &thc->thc_misc); spin_unlock_irqrestore(&par->lock, flags); return 0; @@ -572,7 +533,7 @@ static int cg6_mmap(struct fb_info *info, struct vm_area_struct *vma) static int cg6_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { - struct cg6_par *par = (struct cg6_par *)info->par; + struct cg6_par *par = (struct cg6_par *) info->par; return sbusfb_ioctl_helper(cmd, arg, info, FBTYPE_SUNFAST_COLOR, 8, par->fbsize); @@ -582,14 +543,15 @@ static int cg6_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) * Initialisation */ -static void __devinit cg6_init_fix(struct fb_info *info, int linebytes) +static void +cg6_init_fix(struct fb_info *info, int linebytes) { struct cg6_par *par = (struct cg6_par *)info->par; const char *cg6_cpu_name, *cg6_card_name; u32 conf; conf = sbus_readl(par->fhc); - switch (conf & CG6_FHC_CPU_MASK) { + switch(conf & CG6_FHC_CPU_MASK) { case CG6_FHC_CPU_SPARC: cg6_cpu_name = "sparc"; break; @@ -601,19 +563,21 @@ static void __devinit cg6_init_fix(struct fb_info *info, int linebytes) break; }; if (((conf >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK) >= 11) { - if (par->fbsize <= 0x100000) + if (par->fbsize <= 0x100000) { cg6_card_name = "TGX"; - else + } else { cg6_card_name = "TGX+"; + } } else { - if (par->fbsize <= 0x100000) + if (par->fbsize <= 0x100000) { cg6_card_name = "GX"; - else + } else { cg6_card_name = "GX+"; + } } sprintf(info->fix.id, "%s %s", cg6_card_name, cg6_cpu_name); - info->fix.id[sizeof(info->fix.id) - 1] = 0; + info->fix.id[sizeof(info->fix.id)-1] = 0; info->fix.type = FB_TYPE_PACKED_PIXELS; info->fix.visual = FB_VISUAL_PSEUDOCOLOR; @@ -624,28 +588,28 @@ static void __devinit cg6_init_fix(struct fb_info *info, int linebytes) } /* Initialize Brooktree DAC */ -static void __devinit cg6_bt_init(struct cg6_par *par) +static void cg6_bt_init(struct cg6_par *par) { struct bt_regs __iomem *bt = par->bt; - sbus_writel(0x04 << 24, &bt->addr); /* color planes */ + sbus_writel(0x04 << 24, &bt->addr); /* color planes */ sbus_writel(0xff << 24, &bt->control); sbus_writel(0x05 << 24, &bt->addr); sbus_writel(0x00 << 24, &bt->control); - sbus_writel(0x06 << 24, &bt->addr); /* overlay plane */ + sbus_writel(0x06 << 24, &bt->addr); /* overlay plane */ sbus_writel(0x73 << 24, &bt->control); sbus_writel(0x07 << 24, &bt->addr); sbus_writel(0x00 << 24, &bt->control); } -static void __devinit cg6_chip_init(struct fb_info *info) +static void cg6_chip_init(struct fb_info *info) { - struct cg6_par *par = (struct cg6_par *)info->par; + struct cg6_par *par = (struct cg6_par *) info->par; struct cg6_tec __iomem *tec = par->tec; struct cg6_fbc __iomem *fbc = par->fbc; u32 rev, conf, mode; int i; - + /* Turn off stuff in the Transform Engine. */ sbus_writel(0, &tec->tec_matrix); sbus_writel(0, &tec->tec_clip); @@ -671,13 +635,13 @@ static void __devinit cg6_chip_init(struct fb_info *info) i = sbus_readl(&fbc->s); } while (i & 0x10000000); mode &= ~(CG6_FBC_BLIT_MASK | CG6_FBC_MODE_MASK | - CG6_FBC_DRAW_MASK | CG6_FBC_BWRITE0_MASK | - CG6_FBC_BWRITE1_MASK | CG6_FBC_BREAD_MASK | - CG6_FBC_BDISP_MASK); + CG6_FBC_DRAW_MASK | CG6_FBC_BWRITE0_MASK | + CG6_FBC_BWRITE1_MASK | CG6_FBC_BREAD_MASK | + CG6_FBC_BDISP_MASK); mode |= (CG6_FBC_BLIT_SRC | CG6_FBC_MODE_COLOR8 | - CG6_FBC_DRAW_RENDER | CG6_FBC_BWRITE0_ENABLE | - CG6_FBC_BWRITE1_DISABLE | CG6_FBC_BREAD_0 | - CG6_FBC_BDISP_0); + CG6_FBC_DRAW_RENDER | CG6_FBC_BWRITE0_ENABLE | + CG6_FBC_BWRITE1_DISABLE | CG6_FBC_BREAD_0 | + CG6_FBC_BDISP_0); sbus_writel(mode, &fbc->mode); sbus_writel(0, &fbc->clip); @@ -707,8 +671,7 @@ static void cg6_unmap_regs(struct of_device *op, struct fb_info *info, of_iounmap(&op->resource[0], info->screen_base, par->fbsize); } -static int __devinit cg6_probe(struct of_device *op, - const struct of_device_id *match) +static int __devinit cg6_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; struct fb_info *info; @@ -742,23 +705,22 @@ static int __devinit cg6_probe(struct of_device *op, par->fbsize *= 4; par->fbc = of_ioremap(&op->resource[0], CG6_FBC_OFFSET, - 4096, "cgsix fbc"); + 4096, "cgsix fbc"); par->tec = of_ioremap(&op->resource[0], CG6_TEC_OFFSET, - sizeof(struct cg6_tec), "cgsix tec"); + sizeof(struct cg6_tec), "cgsix tec"); par->thc = of_ioremap(&op->resource[0], CG6_THC_OFFSET, - sizeof(struct cg6_thc), "cgsix thc"); + sizeof(struct cg6_thc), "cgsix thc"); par->bt = of_ioremap(&op->resource[0], CG6_BROOKTREE_OFFSET, - sizeof(struct bt_regs), "cgsix dac"); + sizeof(struct bt_regs), "cgsix dac"); par->fhc = of_ioremap(&op->resource[0], CG6_FHC_OFFSET, - sizeof(u32), "cgsix fhc"); + sizeof(u32), "cgsix fhc"); info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_IMAGEBLIT | - FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT | - FBINFO_READS_FAST; + FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT; info->fbops = &cg6_ops; - info->screen_base = of_ioremap(&op->resource[0], CG6_RAM_OFFSET, - par->fbsize, "cgsix ram"); + 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; diff --git a/trunk/drivers/video/ffb.c b/trunk/drivers/video/ffb.c index d7e24889650e..4b520b573911 100644 --- a/trunk/drivers/video/ffb.c +++ b/trunk/drivers/video/ffb.c @@ -171,17 +171,17 @@ static struct fb_ops ffb_ops = { #define FFB_PPC_CS_VAR 0x000002 #define FFB_PPC_CS_CONST 0x000003 -#define FFB_ROP_NEW 0x83 -#define FFB_ROP_OLD 0x85 -#define FFB_ROP_NEW_XOR_OLD 0x86 - -#define FFB_UCSR_FIFO_MASK 0x00000fff -#define FFB_UCSR_FB_BUSY 0x01000000 -#define FFB_UCSR_RP_BUSY 0x02000000 -#define FFB_UCSR_ALL_BUSY (FFB_UCSR_RP_BUSY|FFB_UCSR_FB_BUSY) -#define FFB_UCSR_READ_ERR 0x40000000 -#define FFB_UCSR_FIFO_OVFL 0x80000000 -#define FFB_UCSR_ALL_ERRORS (FFB_UCSR_READ_ERR|FFB_UCSR_FIFO_OVFL) +#define FFB_ROP_NEW 0x83 +#define FFB_ROP_OLD 0x85 +#define FFB_ROP_NEW_XOR_OLD 0x86 + +#define FFB_UCSR_FIFO_MASK 0x00000fff +#define FFB_UCSR_FB_BUSY 0x01000000 +#define FFB_UCSR_RP_BUSY 0x02000000 +#define FFB_UCSR_ALL_BUSY (FFB_UCSR_RP_BUSY|FFB_UCSR_FB_BUSY) +#define FFB_UCSR_READ_ERR 0x40000000 +#define FFB_UCSR_FIFO_OVFL 0x80000000 +#define FFB_UCSR_ALL_ERRORS (FFB_UCSR_READ_ERR|FFB_UCSR_FIFO_OVFL) struct ffb_fbc { /* Next vertex registers */ @@ -197,7 +197,7 @@ struct ffb_fbc { u32 ryf; u32 rxf; u32 xxx3[2]; - + u32 dmyf; u32 dmxf; u32 xxx4[2]; @@ -211,13 +211,13 @@ struct ffb_fbc { u32 bh; u32 bw; u32 xxx6[2]; - + u32 xxx7[32]; - + /* Setup unit vertex state register */ u32 suvtx; u32 xxx8[63]; - + /* Control registers */ u32 ppc; u32 wid; @@ -235,7 +235,7 @@ struct ffb_fbc { u32 dcsb; u32 dczf; u32 dczb; - + u32 xxx9; u32 blendc; u32 blendc1; @@ -252,7 +252,7 @@ struct ffb_fbc { u32 fbcfg1; u32 fbcfg2; u32 fbcfg3; - + u32 ppcfg; u32 pick; u32 fillmode; @@ -269,7 +269,7 @@ struct ffb_fbc { u32 clip2max; u32 clip3min; u32 clip3max; - + /* New 3dRAM III support regs */ u32 rawblend2; u32 rawpreblend; @@ -287,7 +287,7 @@ struct ffb_fbc { u32 rawcmp; u32 rawwac; u32 fbramid; - + u32 drawop; u32 xxx10[2]; u32 fontlpat; @@ -302,7 +302,7 @@ struct ffb_fbc { u32 stencil; u32 stencilctl; - u32 xxx13[4]; + u32 xxx13[4]; u32 dcss1; u32 dcss2; u32 dcss3; @@ -315,17 +315,17 @@ struct ffb_fbc { u32 dcd3; u32 dcd4; u32 xxx15; - + u32 pattern[32]; - + u32 xxx16[256]; - + u32 devid; u32 xxx17[63]; - + u32 ucsr; u32 xxx18[31]; - + u32 mer; }; @@ -336,20 +336,20 @@ struct ffb_dac { u32 value2; }; -#define FFB_DAC_UCTRL 0x1001 /* User Control */ -#define FFB_DAC_UCTRL_MANREV 0x00000f00 /* 4-bit Manufacturing Revision */ -#define FFB_DAC_UCTRL_MANREV_SHIFT 8 -#define FFB_DAC_TGEN 0x6000 /* Timing Generator */ -#define FFB_DAC_TGEN_VIDE 0x00000001 /* Video Enable */ -#define FFB_DAC_DID 0x8000 /* Device Identification */ -#define FFB_DAC_DID_PNUM 0x0ffff000 /* Device Part Number */ -#define FFB_DAC_DID_PNUM_SHIFT 12 -#define FFB_DAC_DID_REV 0xf0000000 /* Device Revision */ -#define FFB_DAC_DID_REV_SHIFT 28 +#define FFB_DAC_UCTRL 0x1001 /* User Control */ +#define FFB_DAC_UCTRL_MANREV 0x00000f00 /* 4-bit Manufacturing Revision */ +#define FFB_DAC_UCTRL_MANREV_SHIFT 8 +#define FFB_DAC_TGEN 0x6000 /* Timing Generator */ +#define FFB_DAC_TGEN_VIDE 0x00000001 /* Video Enable */ +#define FFB_DAC_DID 0x8000 /* Device Identification */ +#define FFB_DAC_DID_PNUM 0x0ffff000 /* Device Part Number */ +#define FFB_DAC_DID_PNUM_SHIFT 12 +#define FFB_DAC_DID_REV 0xf0000000 /* Device Revision */ +#define FFB_DAC_DID_REV_SHIFT 28 #define FFB_DAC_CUR_CTRL 0x100 -#define FFB_DAC_CUR_CTRL_P0 0x00000001 -#define FFB_DAC_CUR_CTRL_P1 0x00000002 +#define FFB_DAC_CUR_CTRL_P0 0x00000001 +#define FFB_DAC_CUR_CTRL_P1 0x00000002 struct ffb_par { spinlock_t lock; @@ -382,9 +382,7 @@ static void FFBFifo(struct ffb_par *par, int n) if (cache - n < 0) { fbc = par->fbc; - do { - cache = (upa_readl(&fbc->ucsr) & FFB_UCSR_FIFO_MASK); - cache -= 8; + do { cache = (upa_readl(&fbc->ucsr) & FFB_UCSR_FIFO_MASK) - 8; } while (cache - n < 0); } par->fifo_cache = cache - n; @@ -403,12 +401,12 @@ static void FFBWait(struct ffb_par *par) upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr); } udelay(10); - } while (--limit > 0); + } while(--limit > 0); } static int ffb_sync(struct fb_info *p) { - struct ffb_par *par = (struct ffb_par *)p->par; + struct ffb_par *par = (struct ffb_par *) p->par; FFBWait(par); return 0; @@ -433,8 +431,8 @@ static void ffb_switch_from_graph(struct ffb_par *par) FFBWait(par); par->fifo_cache = 0; FFBFifo(par, 7); - upa_writel(FFB_PPC_VCE_DISABLE | FFB_PPC_TBE_OPAQUE | - FFB_PPC_APE_DISABLE | FFB_PPC_CS_CONST, + upa_writel(FFB_PPC_VCE_DISABLE|FFB_PPC_TBE_OPAQUE| + FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST, &fbc->ppc); upa_writel(0x2000707f, &fbc->fbc); upa_writel(par->rop_cache, &fbc->rop); @@ -457,7 +455,7 @@ static void ffb_switch_from_graph(struct ffb_par *par) static int ffb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { - struct ffb_par *par = (struct ffb_par *)info->par; + struct ffb_par *par = (struct ffb_par *) info->par; /* We just use this to catch switches out of * graphics mode. @@ -470,14 +468,16 @@ static int ffb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) } /** - * ffb_fillrect - Draws a rectangle on the screen. + * ffb_fillrect - REQUIRED function. Can use generic routines if + * non acclerated hardware and packed pixel based. + * Draws a rectangle on the screen. * - * @info: frame buffer structure that represents a single frame buffer - * @rect: structure defining the rectagle and operation. + * @info: frame buffer structure that represents a single frame buffer + * @rect: structure defining the rectagle and operation. */ static void ffb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { - struct ffb_par *par = (struct ffb_par *)info->par; + struct ffb_par *par = (struct ffb_par *) info->par; struct ffb_fbc __iomem *fbc = par->fbc; unsigned long flags; u32 fg; @@ -494,9 +494,9 @@ static void ffb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) par->fg_cache = fg; } - ffb_rop(par, rect->rop == ROP_COPY ? - FFB_ROP_NEW : - FFB_ROP_NEW_XOR_OLD); + ffb_rop(par, (rect->rop == ROP_COPY ? + FFB_ROP_NEW : + FFB_ROP_NEW_XOR_OLD)); FFBFifo(par, 5); upa_writel(FFB_DRAWOP_RECTANGLE, &fbc->drawop); @@ -509,15 +509,18 @@ static void ffb_fillrect(struct fb_info *info, const struct fb_fillrect *rect) } /** - * ffb_copyarea - Copies on area of the screen to another area. + * ffb_copyarea - REQUIRED function. Can use generic routines if + * non acclerated hardware and packed pixel based. + * Copies on area of the screen to another area. * - * @info: frame buffer structure that represents a single frame buffer - * @area: structure defining the source and destination. + * @info: frame buffer structure that represents a single frame buffer + * @area: structure defining the source and destination. */ -static void ffb_copyarea(struct fb_info *info, const struct fb_copyarea *area) +static void +ffb_copyarea(struct fb_info *info, const struct fb_copyarea *area) { - struct ffb_par *par = (struct ffb_par *)info->par; + struct ffb_par *par = (struct ffb_par *) info->par; struct ffb_fbc __iomem *fbc = par->fbc; unsigned long flags; @@ -544,14 +547,16 @@ static void ffb_copyarea(struct fb_info *info, const struct fb_copyarea *area) } /** - * ffb_imageblit - Copies a image from system memory to the screen. + * ffb_imageblit - REQUIRED function. Can use generic routines if + * non acclerated hardware and packed pixel based. + * Copies a image from system memory to the screen. * - * @info: frame buffer structure that represents a single frame buffer - * @image: structure defining the image. + * @info: frame buffer structure that represents a single frame buffer + * @image: structure defining the image. */ static void ffb_imageblit(struct fb_info *info, const struct fb_image *image) { - struct ffb_par *par = (struct ffb_par *)info->par; + struct ffb_par *par = (struct ffb_par *) info->par; struct ffb_fbc __iomem *fbc = par->fbc; const u8 *data = image->data; unsigned long flags; @@ -639,14 +644,13 @@ static void ffb_fixup_var_rgb(struct fb_var_screeninfo *var) } /** - * ffb_setcolreg - Sets a color register. - * - * @regno: boolean, 0 copy local, 1 get_user() function - * @red: frame buffer colormap structure - * @green: The green value which can be up to 16 bits wide - * @blue: The blue value which can be up to 16 bits wide. - * @transp: If supported the alpha value which can be up to 16 bits wide. - * @info: frame buffer info structure + * ffb_setcolreg - Optional function. Sets a color register. + * @regno: boolean, 0 copy local, 1 get_user() function + * @red: frame buffer colormap structure + * @green: The green value which can be up to 16 bits wide + * @blue: The blue value which can be up to 16 bits wide. + * @transp: If supported the alpha value which can be up to 16 bits wide. + * @info: frame buffer info structure */ static int ffb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, @@ -668,13 +672,14 @@ static int ffb_setcolreg(unsigned regno, } /** - * ffb_blank - Optional function. Blanks the display. - * @blank_mode: the blank mode we want. - * @info: frame buffer structure that represents a single frame buffer + * ffb_blank - Optional function. Blanks the display. + * @blank_mode: the blank mode we want. + * @info: frame buffer structure that represents a single frame buffer */ -static int ffb_blank(int blank, struct fb_info *info) +static int +ffb_blank(int blank, struct fb_info *info) { - struct ffb_par *par = (struct ffb_par *)info->par; + struct ffb_par *par = (struct ffb_par *) info->par; struct ffb_dac __iomem *dac = par->dac; unsigned long flags; u32 val; @@ -862,7 +867,7 @@ static int ffb_mmap(struct fb_info *info, struct vm_area_struct *vma) static int ffb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) { - struct ffb_par *par = (struct ffb_par *)info->par; + struct ffb_par *par = (struct ffb_par *) info->par; return sbusfb_ioctl_helper(cmd, arg, info, FBTYPE_CREATOR, 24, par->fbsize); @@ -872,7 +877,8 @@ static int ffb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg) * Initialisation */ -static void ffb_init_fix(struct fb_info *info) +static void +ffb_init_fix(struct fb_info *info) { struct ffb_par *par = (struct ffb_par *)info->par; const char *ffb_type_name; @@ -896,8 +902,7 @@ static void ffb_init_fix(struct fb_info *info) info->fix.accel = FB_ACCEL_SUN_CREATOR; } -static int __devinit ffb_probe(struct of_device *op, - const struct of_device_id *match) +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; diff --git a/trunk/drivers/video/xilinxfb.c b/trunk/drivers/video/xilinxfb.c index e38d3b7c3ad7..6ef99b2d13ca 100644 --- a/trunk/drivers/video/xilinxfb.c +++ b/trunk/drivers/video/xilinxfb.c @@ -84,7 +84,7 @@ static struct xilinxfb_platform_data xilinx_fb_default_pdata = { .xres = 640, .yres = 480, .xvirt = 1024, - .yvirt = 480, + .yvirt = 480; }; /* diff --git a/trunk/include/asm-sparc/irqflags.h b/trunk/include/asm-sparc/irqflags.h deleted file mode 100644 index db398fb32826..000000000000 --- a/trunk/include/asm-sparc/irqflags.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * include/asm-sparc/irqflags.h - * - * IRQ flags handling - * - * This file gets included from lowlevel asm headers too, to provide - * wrapped versions of the local_irq_*() APIs, based on the - * raw_local_irq_*() functions from the lowlevel headers. - */ -#ifndef _ASM_IRQFLAGS_H -#define _ASM_IRQFLAGS_H - -#ifndef __ASSEMBLY__ - -extern void raw_local_irq_restore(unsigned long); -extern unsigned long __raw_local_irq_save(void); -extern void raw_local_irq_enable(void); - -static inline unsigned long getipl(void) -{ - unsigned long retval; - - __asm__ __volatile__("rd %%psr, %0" : "=r" (retval)); - return retval; -} - -#define raw_local_save_flags(flags) ((flags) = getipl()) -#define raw_local_irq_save(flags) ((flags) = __raw_local_irq_save()) -#define raw_local_irq_disable() ((void) __raw_local_irq_save()) -#define raw_irqs_disabled() ((getipl() & PSR_PIL) != 0) - -static inline int raw_irqs_disabled_flags(unsigned long flags) -{ - return ((flags & PSR_PIL) != 0); -} - -#endif /* (__ASSEMBLY__) */ - -#endif /* !(_ASM_IRQFLAGS_H) */ diff --git a/trunk/include/asm-sparc/system.h b/trunk/include/asm-sparc/system.h index 8c259de02614..d1a2572e3f55 100644 --- a/trunk/include/asm-sparc/system.h +++ b/trunk/include/asm-sparc/system.h @@ -15,8 +15,6 @@ #ifndef __ASSEMBLY__ -#include - /* * Sparc (general) CPU types */ @@ -166,6 +164,26 @@ extern void fpsave(unsigned long *fpregs, unsigned long *fsr, "o0", "o1", "o2", "o3", "o7"); \ } while(0) +/* + * Changing the IRQ level on the Sparc. + */ +extern void local_irq_restore(unsigned long); +extern unsigned long __local_irq_save(void); +extern void local_irq_enable(void); + +static inline unsigned long getipl(void) +{ + unsigned long retval; + + __asm__ __volatile__("rd %%psr, %0" : "=r" (retval)); + return retval; +} + +#define local_save_flags(flags) ((flags) = getipl()) +#define local_irq_save(flags) ((flags) = __local_irq_save()) +#define local_irq_disable() ((void) __local_irq_save()) +#define irqs_disabled() ((getipl() & PSR_PIL) != 0) + /* XXX Change this if we ever use a PSO mode kernel. */ #define mb() __asm__ __volatile__ ("" : : : "memory") #define rmb() mb() diff --git a/trunk/include/asm-sparc64/cpudata.h b/trunk/include/asm-sparc64/cpudata.h index 542421460a12..98a6e609163e 100644 --- a/trunk/include/asm-sparc64/cpudata.h +++ b/trunk/include/asm-sparc64/cpudata.h @@ -75,11 +75,12 @@ struct trap_per_cpu { unsigned long tsb_huge_temp; /* Dcache line 8: IRQ work list, and keep trap_block a power-of-2 in size. */ - unsigned long irq_worklist_pa; + unsigned int irq_worklist; unsigned int cpu_mondo_qmask; unsigned int dev_mondo_qmask; unsigned int resum_qmask; unsigned int nonresum_qmask; + unsigned int __pad2[1]; void *hdesc; } __attribute__((aligned(64))); extern struct trap_per_cpu trap_block[NR_CPUS]; @@ -127,11 +128,11 @@ extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch, #define TRAP_PER_CPU_CPU_LIST_PA 0xc8 #define TRAP_PER_CPU_TSB_HUGE 0xd0 #define TRAP_PER_CPU_TSB_HUGE_TEMP 0xd8 -#define TRAP_PER_CPU_IRQ_WORKLIST_PA 0xe0 -#define TRAP_PER_CPU_CPU_MONDO_QMASK 0xe8 -#define TRAP_PER_CPU_DEV_MONDO_QMASK 0xec -#define TRAP_PER_CPU_RESUM_QMASK 0xf0 -#define TRAP_PER_CPU_NONRESUM_QMASK 0xf4 +#define TRAP_PER_CPU_IRQ_WORKLIST 0xe0 +#define TRAP_PER_CPU_CPU_MONDO_QMASK 0xe4 +#define TRAP_PER_CPU_DEV_MONDO_QMASK 0xe8 +#define TRAP_PER_CPU_RESUM_QMASK 0xec +#define TRAP_PER_CPU_NONRESUM_QMASK 0xf0 #define TRAP_BLOCK_SZ_SHIFT 8 @@ -183,9 +184,9 @@ extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch, ldx [DEST + TRAP_PER_CPU_PGD_PADDR], DEST; /* Clobbers TMP, loads local processor's IRQ work area into DEST. */ -#define TRAP_LOAD_IRQ_WORK_PA(DEST, TMP) \ +#define TRAP_LOAD_IRQ_WORK(DEST, TMP) \ TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \ - add DEST, TRAP_PER_CPU_IRQ_WORKLIST_PA, DEST; + add DEST, TRAP_PER_CPU_IRQ_WORKLIST, DEST; /* Clobbers TMP, loads DEST with current thread info pointer. */ #define TRAP_LOAD_THREAD_REG(DEST, TMP) \ @@ -222,9 +223,9 @@ extern struct sun4v_2insn_patch_entry __sun4v_2insn_patch, ldx [DEST + TRAP_PER_CPU_PGD_PADDR], DEST; /* Clobbers TMP, loads local processor's IRQ work area into DEST. */ -#define TRAP_LOAD_IRQ_WORK_PA(DEST, TMP) \ +#define TRAP_LOAD_IRQ_WORK(DEST, TMP) \ TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \ - add DEST, TRAP_PER_CPU_IRQ_WORKLIST_PA, DEST; + add DEST, TRAP_PER_CPU_IRQ_WORKLIST, DEST; #define TRAP_LOAD_THREAD_REG(DEST, TMP) \ TRAP_LOAD_TRAP_BLOCK(DEST, TMP) \ diff --git a/trunk/include/asm-sparc64/irq.h b/trunk/include/asm-sparc64/irq.h index 182dba05c702..c00ad152771b 100644 --- a/trunk/include/asm-sparc64/irq.h +++ b/trunk/include/asm-sparc64/irq.h @@ -51,19 +51,10 @@ extern unsigned int sun4v_build_msi(u32 devhandle, unsigned int *virt_irq_p, unsigned int msi_devino_start, unsigned int msi_devino_end); extern void sun4v_destroy_msi(unsigned int virt_irq); -extern unsigned int sun4u_build_msi(u32 portid, unsigned int *virt_irq_p, - unsigned int msi_devino_start, - unsigned int msi_devino_end, - unsigned long imap_base, - unsigned long iclr_base); -extern void sun4u_destroy_msi(unsigned int virt_irq); extern unsigned int sbus_build_irq(void *sbus, unsigned int ino); -extern unsigned char virt_irq_alloc(unsigned int dev_handle, - unsigned int dev_ino); -#ifdef CONFIG_PCI_MSI -extern void virt_irq_free(unsigned int virt_irq); -#endif +extern void sparc64_set_msi(unsigned int virt_irq, u32 msi); +extern u32 sparc64_get_msi(unsigned int virt_irq); extern void fixup_irqs(void);