Skip to content

Commit

Permalink
[PATCH] s390: external call performance
Browse files Browse the repository at this point in the history
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: Martin Schwidefsky <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
heicarst authored and Linus Torvalds committed Jul 27, 2005
1 parent 46ee058 commit 99b2d8d
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 13 deletions.
2 changes: 1 addition & 1 deletion arch/s390/kernel/head.S
Original file line number Diff line number Diff line change
Expand Up @@ -765,7 +765,7 @@ _stext: basr %r13,0 # get base

# check control registers
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
lctl %c0,%c15,0(%r15)

Expand Down
2 changes: 1 addition & 1 deletion arch/s390/kernel/head64.S
Original file line number Diff line number Diff line change
Expand Up @@ -762,7 +762,7 @@ _stext: basr %r13,0 # get base

# check control registers
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
lctlg %c0,%c15,0(%r15)

Expand Down
16 changes: 10 additions & 6 deletions arch/s390/kernel/s390_ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,18 @@
#include <asm/irq.h>

/*
* Simple hash strategy: index = code & 0xff;
* 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
* (0x1202 external call, 0x1004 cpu timer, 0x2401 hwc console, 0x4000
* iucv and 0x2603 pfault) this is always the first element.
*/
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)
{
ext_int_info_t *p;
Expand All @@ -37,7 +41,7 @@ int register_external_interrupt(__u16 code, ext_int_handler_t handler)
return -ENOMEM;
p->code = code;
p->handler = handler;
index = code & 0xff;
index = ext_hash(code);
p->next = ext_int_hash[index];
ext_int_hash[index] = p;
return 0;
Expand All @@ -52,7 +56,7 @@ int register_early_external_interrupt(__u16 code, ext_int_handler_t handler,
return -EINVAL;
p->code = code;
p->handler = handler;
index = code & 0xff;
index = ext_hash(code);
p->next = ext_int_hash[index];
ext_int_hash[index] = p;
return 0;
Expand All @@ -63,7 +67,7 @@ int unregister_external_interrupt(__u16 code, ext_int_handler_t handler)
ext_int_info_t *p, *q;
int index;

index = code & 0xff;
index = ext_hash(code);
q = NULL;
p = ext_int_hash[index];
while (p != NULL) {
Expand All @@ -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)
return -EINVAL;
index = code & 0xff;
index = ext_hash(code);
q = ext_int_hash[index];
if (p != q) {
while (q != NULL) {
Expand Down Expand Up @@ -120,7 +124,7 @@ void do_extint(struct pt_regs *regs, unsigned short code)
*/
account_ticks(regs);
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) {
if (likely(p->code == code)) {
if (likely(p->handler))
Expand Down
10 changes: 5 additions & 5 deletions arch/s390/kernel/smp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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_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);
}

Expand All @@ -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_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);
}
}
Expand Down Expand Up @@ -751,9 +751,9 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
unsigned int cpu;
int i;

/* request the 0x1202 external interrupt */
if (register_external_interrupt(0x1202, do_ext_call_interrupt) != 0)
panic("Couldn't request external interrupt 0x1202");
/* request the 0x1201 emergency signal external interrupt */
if (register_external_interrupt(0x1201, do_ext_call_interrupt) != 0)
panic("Couldn't request external interrupt 0x1201");
smp_check_cpus(max_cpus);
memset(lowcore_ptr,0,sizeof(lowcore_ptr));
/*
Expand Down

0 comments on commit 99b2d8d

Please sign in to comment.