diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-14 08:59:48 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-14 08:59:48 -0700 |
commit | cbe619b162121577bc1e8ed4384dfb85f19e43d8 (patch) | |
tree | a26287f4fcb2ae732ac3f5ee1e18473de8a2247a /arch | |
parent | 5dd80d5d096f58b7a83ae493a20bfc9d0de30226 (diff) | |
parent | 45b3f4cc6025bdb14beb65b8a3a732bf55d1bc41 (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6
* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/sparc-2.6: (23 commits)
[SPARC64]: virt_to_real_irq_table --> virt_irq_table
[SPARC64]: virt_irq --> bucket mapping no longer necessary
[SPARC64]: Kill ugly __bucket() macro.
[SPARC64]: Kill ugly __irq_ino() macro.
[SPARC64]: Only use bypass accesses to INO buckets.
[SPARC64]: Update defconfig.
[SPARC64]: Use sun4v VIRQ interfaces as intended.
[SPARC64]: Allocate ivector_table dynamically.
[SPARC64]: Access ivector_table[] using physical addresses.
[SPARC64]: Make IVEC pointers 64-bit.
[SPARC64]: Fix register usage in xor_raid_4().
[SPARC64]: Kill pci_memspace_mask.
[SPARC64]: Consolidate MSI support code.
[SPARC/64]: Move of_platform_driver initialisations: arch/sparc{,64}.
[SPARC64]: Fix bugs in SYSV IPC handling in 64-bit processes.
[SPARC/64]: Prepare to remove of_platform_driver name.
[SPARC32]: Add irqflags.h to sparc32 and use it from generic code.
[SPARC64]: beautify vmlinux.lds
[SPARC]: beautify vmlinux.lds
[SPARC64]: Enable MSI on sun4u Fire PCI-E controllers.
...
Diffstat (limited to 'arch')
26 files changed, 1451 insertions, 903 deletions
diff --git a/arch/sparc/Kconfig.debug b/arch/sparc/Kconfig.debug index 120f6b52934..87dd496f15e 100644 --- a/arch/sparc/Kconfig.debug +++ b/arch/sparc/Kconfig.debug @@ -1,5 +1,9 @@ menu "Kernel hacking" +config TRACE_IRQFLAGS_SUPPORT + bool + default y + source "lib/Kconfig.debug" config DEBUG_STACK_USAGE diff --git a/arch/sparc/kernel/irq.c b/arch/sparc/kernel/irq.c index b76dc03fc31..722d67d3296 100644 --- a/arch/sparc/kernel/irq.c +++ b/arch/sparc/kernel/irq.c @@ -56,7 +56,7 @@ #define SMP_NOP2 #define SMP_NOP3 #endif /* SMP */ -unsigned long __local_irq_save(void) +unsigned long __raw_local_irq_save(void) { unsigned long retval; unsigned long tmp; @@ -74,7 +74,7 @@ unsigned long __local_irq_save(void) return retval; } -void local_irq_enable(void) +void raw_local_irq_enable(void) { unsigned long tmp; @@ -89,7 +89,7 @@ void local_irq_enable(void) : "memory"); } -void local_irq_restore(unsigned long old_psr) +void raw_local_irq_restore(unsigned long old_psr) { unsigned long tmp; @@ -105,9 +105,9 @@ void local_irq_restore(unsigned long old_psr) : "memory"); } -EXPORT_SYMBOL(__local_irq_save); -EXPORT_SYMBOL(local_irq_enable); -EXPORT_SYMBOL(local_irq_restore); +EXPORT_SYMBOL(__raw_local_irq_save); +EXPORT_SYMBOL(raw_local_irq_enable); +EXPORT_SYMBOL(raw_local_irq_restore); /* * Dave Redman (djhr@tadpole.co.uk) diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c index 36383f73d68..fb2caef79ce 100644 --- a/arch/sparc/kernel/of_device.c +++ b/arch/sparc/kernel/of_device.c @@ -588,7 +588,10 @@ __setup("of_debug=", of_debug); int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus) { /* initialize common driver fields */ - drv->driver.name = drv->name; + if (!drv->driver.name) + drv->driver.name = drv->name; + if (!drv->driver.owner) + drv->driver.owner = drv->owner; drv->driver.bus = bus; /* register with core */ diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index 6a251332162..4bf78a5e8e0 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c @@ -347,9 +347,11 @@ 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/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S index 15109c156e8..a8b4200f9cc 100644 --- a/arch/sparc/kernel/vmlinux.lds.S +++ b/arch/sparc/kernel/vmlinux.lds.S @@ -1,6 +1,7 @@ /* ld script to make SparcLinux kernel */ #include <asm-generic/vmlinux.lds.h> +#include <asm/page.h> OUTPUT_FORMAT("elf32-sparc", "elf32-sparc", "elf32-sparc") OUTPUT_ARCH(sparc) @@ -8,84 +9,104 @@ 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 = .); - __start___fixup = .; - .fixup : { *(.fixup) } - __stop___fixup = .; - __start___ex_table = .; - __ex_table : { *(__ex_table) } - __stop___ex_table = .; + . = 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 = .); - NOTES + .fixup : { + __start___fixup = .; + *(.fixup) + __stop___fixup = .; + } + __ex_table : { + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; + } - . = 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 + 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 #ifdef CONFIG_BLK_DEV_INITRD - . = ALIGN(4096); - __initramfs_start = .; - .init.ramfs : { *(.init.ramfs) } - __initramfs_end = .; + . = ALIGN(PAGE_SIZE); + .init.ramfs : { + __initramfs_start = .; + *(.init.ramfs) + __initramfs_end = .; + } #endif - 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) } + PERCPU(PAGE_SIZE) + . = ALIGN(PAGE_SIZE); + __init_end = .; + . = ALIGN(32); + .data.cacheline_aligned : { + *(.data.cacheline_aligned) + } - STABS_DEBUG + __bss_start = .; + .sbss : { + *(.sbss) + *(.scommon) } + .bss : { + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); + /DISCARD/ : { + *(.exit.text) + *(.exit.data) + *(.exitcall.exit) + } - DWARF_DEBUG + STABS_DEBUG + DWARF_DEBUG } diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index 7d07297db87..1aa2c4048e4 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.23-rc6 -# Sun Sep 16 09:52:11 2007 +# Linux kernel version: 2.6.23 +# Sat Oct 13 21:53:54 2007 # CONFIG_SPARC=y CONFIG_SPARC64=y @@ -69,7 +69,6 @@ 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 @@ -89,6 +88,7 @@ CONFIG_KMOD=y CONFIG_BLOCK=y CONFIG_BLK_DEV_IO_TRACE=y CONFIG_BLK_DEV_BSG=y +CONFIG_BLOCK_COMPAT=y # # IO Schedulers @@ -111,6 +111,7 @@ 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 @@ -119,6 +120,8 @@ 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 @@ -213,6 +216,7 @@ 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 @@ -304,6 +308,7 @@ 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 @@ -355,6 +360,11 @@ 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 @@ -391,7 +401,6 @@ 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 # @@ -505,6 +514,8 @@ 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 @@ -518,13 +529,16 @@ 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 @@ -543,6 +557,7 @@ 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 @@ -560,11 +575,14 @@ 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 # @@ -820,6 +838,12 @@ CONFIG_HWMON=y # CONFIG_HWMON_DEBUG_CHIP is not set # +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set + +# # Multifunction device drivers # # CONFIG_MFD_SM501 is not set @@ -1399,6 +1423,7 @@ 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 @@ -1417,6 +1442,7 @@ 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 @@ -1431,11 +1457,13 @@ 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/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index 40d2f3aae91..112c46e6657 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -18,6 +18,7 @@ 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/arch/sparc64/kernel/auxio.c b/arch/sparc64/kernel/auxio.c index 7b379761e9f..c55f0293eac 100644 --- a/arch/sparc64/kernel/auxio.c +++ b/arch/sparc64/kernel/auxio.c @@ -148,9 +148,11 @@ 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/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index 8059531bf0a..c9b0d7af64a 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -429,16 +429,16 @@ do_ivec: stxa %g0, [%g0] ASI_INTR_RECEIVE membar #Sync - sethi %hi(ivector_table), %g2 - sllx %g3, 3, %g3 - or %g2, %lo(ivector_table), %g2 + sethi %hi(ivector_table_pa), %g2 + ldx [%g2 + %lo(ivector_table_pa)], %g2 + sllx %g3, 4, %g3 add %g2, %g3, %g3 - TRAP_LOAD_IRQ_WORK(%g6, %g1) + TRAP_LOAD_IRQ_WORK_PA(%g6, %g1) - lduw [%g6], %g5 /* g5 = irq_work(cpu) */ - stw %g5, [%g3 + 0x00] /* bucket->irq_chain = g5 */ - stw %g3, [%g6] /* irq_work(cpu) = bucket */ + ldx [%g6], %g5 + stxa %g5, [%g3] ASI_PHYS_USE_EC + stx %g3, [%g6] wr %g0, 1 << PIL_DEVICE_IRQ, %set_softint retry do_ivec_xcall: diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 23956096b3b..f3922e5a89f 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c @@ -21,7 +21,6 @@ #include <linux/seq_file.h> #include <linux/bootmem.h> #include <linux/irq.h> -#include <linux/msi.h> #include <asm/ptrace.h> #include <asm/processor.h> @@ -43,6 +42,7 @@ #include <asm/auxio.h> #include <asm/head.h> #include <asm/hypervisor.h> +#include <asm/cacheflush.h> /* UPA nodes send interrupt packet to UltraSparc with first data reg * value low 5 (7 on Starfire) bits holding the IRQ identifier being @@ -52,86 +52,128 @@ * 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 { - /* 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; +/*0x00*/unsigned long __irq_chain_pa; /* Virtual interrupt number assigned to this INO. */ -/*0x04*/unsigned int virt_irq; +/*0x08*/unsigned int __virt_irq; +/*0x0c*/unsigned int __pad; }; #define NUM_IVECS (IMAP_INR + 1) -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. +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. */ -#define irq_work(__cpu) &(trap_block[(__cpu)].irq_worklist) +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) static struct { - unsigned int irq; unsigned int dev_handle; unsigned int dev_ino; -} virt_to_real_irq_table[NR_IRQS]; + unsigned int in_use; +} virt_irq_table[NR_IRQS]; +static DEFINE_SPINLOCK(virt_irq_alloc_lock); -static unsigned char virt_irq_alloc(unsigned int real_irq) +unsigned char virt_irq_alloc(unsigned int dev_handle, + unsigned int dev_ino) { + 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_to_real_irq_table[ent].irq) + if (!virt_irq_table[ent].in_use) break; } if (ent >= NR_IRQS) { printk(KERN_ERR "IRQ: Out of virtual IRQs.\n"); - return 0; + 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; } - virt_to_real_irq_table[ent].irq = real_irq; + spin_unlock_irqrestore(&virt_irq_alloc_lock, flags); return ent; } #ifdef CONFIG_PCI_MSI -static void virt_irq_free(unsigned int virt_irq) +void virt_irq_free(unsigned int virt_irq) { - unsigned int real_irq; + unsigned long flags; if (virt_irq >= NR_IRQS) return; - real_irq = virt_to_real_irq_table[virt_irq].irq; - virt_to_real_irq_table[virt_irq].irq = 0; + spin_lock_irqsave(&virt_irq_alloc_lock, flags); - __bucket(real_irq)->virt_irq = 0; -} -#endif + virt_irq_table[virt_irq].in_use = 0; -static unsigned int virt_to_real_irq(unsigned char virt_irq) -{ - return virt_to_real_irq_table[virt_irq].irq; + spin_unlock_irqrestore(&virt_irq_alloc_lock, flags); } +#endif /* * /proc/interrupts printing: @@ -217,38 +259,8 @@ 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) { @@ -348,201 +360,152 @@ static void sun4u_irq_end(unsigned int virt_irq) static void sun4v_irq_enable(unsigned int virt_irq) { - 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; + unsigned int ino = virt_irq_table[virt_irq].dev_ino; + unsigned long cpuid = irq_choose_cpu(virt_irq); + 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); - 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); - } + 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) { - struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); - unsigned int ino = bucket - &ivector_table[0]; + unsigned int ino = virt_irq_table[virt_irq].dev_ino; + unsigned long cpuid = irq_choose_cpu(virt_irq); + int 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); - } + 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) { - 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); -} + unsigned int ino = virt_irq_table[virt_irq].dev_ino; + int err; -static void sun4v_msi_disable(unsigned int virt_irq) -{ - mask_msi_irq(virt_irq); - sun4v_irq_disable(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); } -#endif static void sun4v_irq_end(unsigned int virt_irq) { - struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); - unsigned int ino = bucket - &ivector_table[0]; + unsigned int ino = virt_irq_table[virt_irq].dev_ino; struct irq_desc *desc = irq_desc + virt_irq; + int err; if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) return; - 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); - } + 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) { - 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); - } + 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); } static void sun4v_virt_set_affinity(unsigned int virt_irq, cpumask_t mask) { - struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); + unsigned long cpuid, dev_handle, dev_ino; + int err; - if (likely(bucket)) { - unsigned long cpuid, dev_handle, dev_ino; - int err; + cpuid = irq_choose_cpu(virt_irq); - cpuid = irq_choose_cpu(virt_irq); + dev_handle = virt_irq_table[virt_irq].dev_han |