From 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 16 Apr 2005 15:20:36 -0700 Subject: Linux-2.6.12-rc2 Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip! --- arch/s390/kernel/s390_ext.c | 135 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 arch/s390/kernel/s390_ext.c (limited to 'arch/s390/kernel/s390_ext.c') diff --git a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c new file mode 100644 index 000000000000..3bdd38ec71da --- /dev/null +++ b/arch/s390/kernel/s390_ext.c @@ -0,0 +1,135 @@ +/* + * arch/s390/kernel/s390_ext.c + * + * S390 version + * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com), + * Martin Schwidefsky (schwidefsky@de.ibm.com) + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * 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, }; + +int register_external_interrupt(__u16 code, ext_int_handler_t handler) +{ + ext_int_info_t *p; + int index; + + p = (ext_int_info_t *) kmalloc(sizeof(ext_int_info_t), GFP_ATOMIC); + if (p == NULL) + return -ENOMEM; + p->code = code; + p->handler = handler; + index = code & 0xff; + p->next = ext_int_hash[index]; + ext_int_hash[index] = p; + return 0; +} + +int register_early_external_interrupt(__u16 code, ext_int_handler_t handler, + ext_int_info_t *p) +{ + int index; + + if (p == NULL) + return -EINVAL; + p->code = code; + p->handler = handler; + index = code & 0xff; + p->next = ext_int_hash[index]; + ext_int_hash[index] = p; + return 0; +} + +int unregister_external_interrupt(__u16 code, ext_int_handler_t handler) +{ + ext_int_info_t *p, *q; + int index; + + index = code & 0xff; + q = NULL; + p = ext_int_hash[index]; + while (p != NULL) { + if (p->code == code && p->handler == handler) + break; + q = p; + p = p->next; + } + if (p == NULL) + return -ENOENT; + if (q != NULL) + q->next = p->next; + else + ext_int_hash[index] = p->next; + kfree(p); + return 0; +} + +int unregister_early_external_interrupt(__u16 code, ext_int_handler_t handler, + ext_int_info_t *p) +{ + ext_int_info_t *q; + int index; + + if (p == NULL || p->code != code || p->handler != handler) + return -EINVAL; + index = code & 0xff; + q = ext_int_hash[index]; + if (p != q) { + while (q != NULL) { + if (q->next == p) + break; + q = q->next; + } + if (q == NULL) + return -ENOENT; + q->next = p->next; + } else + ext_int_hash[index] = p->next; + return 0; +} + +void do_extint(struct pt_regs *regs, unsigned short code) +{ + ext_int_info_t *p; + int index; + + irq_enter(); + asm volatile ("mc 0,0"); + if (S390_lowcore.int_clock >= S390_lowcore.jiffy_timer) + /** + * Make sure that the i/o interrupt did not "overtake" + * the last HZ timer interrupt. + */ + account_ticks(regs); + kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++; + index = code & 0xff; + for (p = ext_int_hash[index]; p; p = p->next) { + if (likely(p->code == code)) { + if (likely(p->handler)) + p->handler(regs, code); + } + } + irq_exit(); +} + +EXPORT_SYMBOL(register_external_interrupt); +EXPORT_SYMBOL(unregister_external_interrupt); + -- cgit v1.2.3