aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-14 08:59:48 -0700
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-14 08:59:48 -0700
commitcbe619b162121577bc1e8ed4384dfb85f19e43d8 (patch)
treea26287f4fcb2ae732ac3f5ee1e18473de8a2247a /arch
parent5dd80d5d096f58b7a83ae493a20bfc9d0de30226 (diff)
parent45b3f4cc6025bdb14beb65b8a3a732bf55d1bc41 (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')
-rw-r--r--arch/sparc/Kconfig.debug4
-rw-r--r--arch/sparc/kernel/irq.c12
-rw-r--r--arch/sparc/kernel/of_device.c5
-rw-r--r--arch/sparc/kernel/time.c4
-rw-r--r--arch/sparc/kernel/vmlinux.lds.S165
-rw-r--r--arch/sparc64/defconfig38
-rw-r--r--arch/sparc64/kernel/Makefile1
-rw-r--r--arch/sparc64/kernel/auxio.c4
-rw-r--r--arch/sparc64/kernel/entry.S14
-rw-r--r--arch/sparc64/kernel/irq.c610
-rw-r--r--arch/sparc64/kernel/of_device.c5
-rw-r--r--arch/sparc64/kernel/pci.c60
-rw-r--r--arch/sparc64/kernel/pci_fire.c279
-rw-r--r--arch/sparc64/kernel/pci_impl.h32
-rw-r--r--arch/sparc64/kernel/pci_msi.c433
-rw-r--r--arch/sparc64/kernel/pci_psycho.c6
-rw-r--r--arch/sparc64/kernel/pci_schizo.c3
-rw-r--r--arch/sparc64/kernel/pci_sun4v.c405
-rw-r--r--arch/sparc64/kernel/power.c4
-rw-r--r--arch/sparc64/kernel/sun4v_ivec.S22
-rw-r--r--arch/sparc64/kernel/sys_sparc.c15
-rw-r--r--arch/sparc64/kernel/time.c4
-rw-r--r--arch/sparc64/kernel/traps.c4
-rw-r--r--arch/sparc64/kernel/vmlinux.lds.S211
-rw-r--r--arch/sparc64/lib/xor.S12
-rw-r--r--arch/sparc64/mm/init.c2
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