Commit 99b2d8df authored by Heiko Carstens's avatar Heiko Carstens Committed by Linus Torvalds

[PATCH] s390: external call performance

The kernel uses the SIGP external call order code to signal other CPUs.  When
running with dedicated CPUs external calls don't get delivered immediately but
within a fixed polling invervall.  This can lead to delays where the system
appears to do nothing.  Replace the SIGP external call order with the SIGP
emergency call order since this one gets delivered immediately.
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 46ee058c
...@@ -765,7 +765,7 @@ _stext: basr %r13,0 # get base ...@@ -765,7 +765,7 @@ _stext: basr %r13,0 # get base
# check control registers # check control registers
stctl %c0,%c15,0(%r15) stctl %c0,%c15,0(%r15)
oi 2(%r15),0x20 # enable sigp external interrupts oi 2(%r15),0x40 # enable sigp emergency signal
oi 0(%r15),0x10 # switch on low address protection oi 0(%r15),0x10 # switch on low address protection
lctl %c0,%c15,0(%r15) lctl %c0,%c15,0(%r15)
......
...@@ -762,7 +762,7 @@ _stext: basr %r13,0 # get base ...@@ -762,7 +762,7 @@ _stext: basr %r13,0 # get base
# check control registers # check control registers
stctg %c0,%c15,0(%r15) stctg %c0,%c15,0(%r15)
oi 6(%r15),0x20 # enable sigp external interrupts oi 6(%r15),0x40 # enable sigp emergency signal
oi 4(%r15),0x10 # switch on low address proctection oi 4(%r15),0x10 # switch on low address proctection
lctlg %c0,%c15,0(%r15) lctlg %c0,%c15,0(%r15)
......
...@@ -19,7 +19,6 @@ ...@@ -19,7 +19,6 @@
#include <asm/irq.h> #include <asm/irq.h>
/* /*
* Simple hash strategy: index = code & 0xff;
* ext_int_hash[index] is the start of the list for all external interrupts * ext_int_hash[index] is the start of the list for all external interrupts
* that hash to this index. With the current set of external interrupts * that hash to this index. With the current set of external interrupts
* (0x1202 external call, 0x1004 cpu timer, 0x2401 hwc console, 0x4000 * (0x1202 external call, 0x1004 cpu timer, 0x2401 hwc console, 0x4000
...@@ -27,6 +26,11 @@ ...@@ -27,6 +26,11 @@
*/ */
ext_int_info_t *ext_int_hash[256] = { 0, }; ext_int_info_t *ext_int_hash[256] = { 0, };
static inline int ext_hash(__u16 code)
{
return (code + (code >> 9)) & 0xff;
}
int register_external_interrupt(__u16 code, ext_int_handler_t handler) int register_external_interrupt(__u16 code, ext_int_handler_t handler)
{ {
ext_int_info_t *p; ext_int_info_t *p;
...@@ -37,7 +41,7 @@ int register_external_interrupt(__u16 code, ext_int_handler_t handler) ...@@ -37,7 +41,7 @@ int register_external_interrupt(__u16 code, ext_int_handler_t handler)
return -ENOMEM; return -ENOMEM;
p->code = code; p->code = code;
p->handler = handler; p->handler = handler;
index = code & 0xff; index = ext_hash(code);
p->next = ext_int_hash[index]; p->next = ext_int_hash[index];
ext_int_hash[index] = p; ext_int_hash[index] = p;
return 0; return 0;
...@@ -52,7 +56,7 @@ int register_early_external_interrupt(__u16 code, ext_int_handler_t handler, ...@@ -52,7 +56,7 @@ int register_early_external_interrupt(__u16 code, ext_int_handler_t handler,
return -EINVAL; return -EINVAL;
p->code = code; p->code = code;
p->handler = handler; p->handler = handler;
index = code & 0xff; index = ext_hash(code);
p->next = ext_int_hash[index]; p->next = ext_int_hash[index];
ext_int_hash[index] = p; ext_int_hash[index] = p;
return 0; return 0;
...@@ -63,7 +67,7 @@ int unregister_external_interrupt(__u16 code, ext_int_handler_t handler) ...@@ -63,7 +67,7 @@ int unregister_external_interrupt(__u16 code, ext_int_handler_t handler)
ext_int_info_t *p, *q; ext_int_info_t *p, *q;
int index; int index;
index = code & 0xff; index = ext_hash(code);
q = NULL; q = NULL;
p = ext_int_hash[index]; p = ext_int_hash[index];
while (p != NULL) { while (p != NULL) {
...@@ -90,7 +94,7 @@ int unregister_early_external_interrupt(__u16 code, ext_int_handler_t handler, ...@@ -90,7 +94,7 @@ int unregister_early_external_interrupt(__u16 code, ext_int_handler_t handler,
if (p == NULL || p->code != code || p->handler != handler) if (p == NULL || p->code != code || p->handler != handler)
return -EINVAL; return -EINVAL;
index = code & 0xff; index = ext_hash(code);
q = ext_int_hash[index]; q = ext_int_hash[index];
if (p != q) { if (p != q) {
while (q != NULL) { while (q != NULL) {
...@@ -120,7 +124,7 @@ void do_extint(struct pt_regs *regs, unsigned short code) ...@@ -120,7 +124,7 @@ void do_extint(struct pt_regs *regs, unsigned short code)
*/ */
account_ticks(regs); account_ticks(regs);
kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++; kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++;
index = code & 0xff; index = ext_hash(code);
for (p = ext_int_hash[index]; p; p = p->next) { for (p = ext_int_hash[index]; p; p = p->next) {
if (likely(p->code == code)) { if (likely(p->code == code)) {
if (likely(p->handler)) if (likely(p->handler))
......
...@@ -375,7 +375,7 @@ static void smp_ext_bitcall(int cpu, ec_bit_sig sig) ...@@ -375,7 +375,7 @@ static void smp_ext_bitcall(int cpu, ec_bit_sig sig)
* Set signaling bit in lowcore of target cpu and kick it * Set signaling bit in lowcore of target cpu and kick it
*/ */
set_bit(sig, (unsigned long *) &lowcore_ptr[cpu]->ext_call_fast); set_bit(sig, (unsigned long *) &lowcore_ptr[cpu]->ext_call_fast);
while(signal_processor(cpu, sigp_external_call) == sigp_busy) while(signal_processor(cpu, sigp_emergency_signal) == sigp_busy)
udelay(10); udelay(10);
} }
...@@ -394,7 +394,7 @@ static void smp_ext_bitcall_others(ec_bit_sig sig) ...@@ -394,7 +394,7 @@ static void smp_ext_bitcall_others(ec_bit_sig sig)
* Set signaling bit in lowcore of target cpu and kick it * Set signaling bit in lowcore of target cpu and kick it
*/ */
set_bit(sig, (unsigned long *) &lowcore_ptr[cpu]->ext_call_fast); set_bit(sig, (unsigned long *) &lowcore_ptr[cpu]->ext_call_fast);
while (signal_processor(cpu, sigp_external_call) == sigp_busy) while (signal_processor(cpu, sigp_emergency_signal) == sigp_busy)
udelay(10); udelay(10);
} }
} }
...@@ -751,9 +751,9 @@ void __init smp_prepare_cpus(unsigned int max_cpus) ...@@ -751,9 +751,9 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
unsigned int cpu; unsigned int cpu;
int i; int i;
/* request the 0x1202 external interrupt */ /* request the 0x1201 emergency signal external interrupt */
if (register_external_interrupt(0x1202, do_ext_call_interrupt) != 0) if (register_external_interrupt(0x1201, do_ext_call_interrupt) != 0)
panic("Couldn't request external interrupt 0x1202"); panic("Couldn't request external interrupt 0x1201");
smp_check_cpus(max_cpus); smp_check_cpus(max_cpus);
memset(lowcore_ptr,0,sizeof(lowcore_ptr)); memset(lowcore_ptr,0,sizeof(lowcore_ptr));
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment