Commit fde15c3a authored by Heiko Carstens's avatar Heiko Carstens Committed by Martin Schwidefsky

[S390] irq: external interrupt code passing

The external interrupt handlers have a parameter called ext_int_code.
Besides the name this paramter does not only contain the ext_int_code
but in addition also the "cpu address" (POP) which caused the external
interrupt.
To make the code a bit more obvious pass a struct instead so the called
function can easily distinguish between external interrupt code and
cpu address. The cpu address field however is named "subcode" since
some external interrupt sources do not pass a cpu address but a
different parameter (or none at all).
Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 2215011d
...@@ -34,7 +34,12 @@ enum interruption_class { ...@@ -34,7 +34,12 @@ enum interruption_class {
NR_IRQS, NR_IRQS,
}; };
typedef void (*ext_int_handler_t)(unsigned int, unsigned int, unsigned long); struct ext_code {
unsigned short subcode;
unsigned short code;
};
typedef void (*ext_int_handler_t)(struct ext_code, unsigned int, unsigned long);
int register_external_interrupt(u16 code, ext_int_handler_t handler); int register_external_interrupt(u16 code, ext_int_handler_t handler);
int unregister_external_interrupt(u16 code, ext_int_handler_t handler); int unregister_external_interrupt(u16 code, ext_int_handler_t handler);
......
...@@ -35,7 +35,8 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka, ...@@ -35,7 +35,8 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs); siginfo_t *info, sigset_t *oldset, struct pt_regs *regs);
void do_notify_resume(struct pt_regs *regs); void do_notify_resume(struct pt_regs *regs);
void do_extint(struct pt_regs *regs, unsigned int, unsigned int, unsigned long); struct ext_code;
void do_extint(struct pt_regs *regs, struct ext_code, unsigned int, unsigned long);
void do_restart(void); void do_restart(void);
void __init startup_init(void); void __init startup_init(void);
void die(struct pt_regs *regs, const char *str); void die(struct pt_regs *regs, const char *str);
......
...@@ -209,29 +209,27 @@ int unregister_external_interrupt(u16 code, ext_int_handler_t handler) ...@@ -209,29 +209,27 @@ int unregister_external_interrupt(u16 code, ext_int_handler_t handler)
} }
EXPORT_SYMBOL(unregister_external_interrupt); EXPORT_SYMBOL(unregister_external_interrupt);
void __irq_entry do_extint(struct pt_regs *regs, unsigned int ext_int_code, void __irq_entry do_extint(struct pt_regs *regs, struct ext_code ext_code,
unsigned int param32, unsigned long param64) unsigned int param32, unsigned long param64)
{ {
struct pt_regs *old_regs; struct pt_regs *old_regs;
unsigned short code;
struct ext_int_info *p; struct ext_int_info *p;
int index; int index;
code = (unsigned short) ext_int_code;
old_regs = set_irq_regs(regs); old_regs = set_irq_regs(regs);
irq_enter(); irq_enter();
if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator)
/* Serve timer interrupts first. */ /* Serve timer interrupts first. */
clock_comparator_work(); clock_comparator_work();
kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++; kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++;
if (code != 0x1004) if (ext_code.code != 0x1004)
__get_cpu_var(s390_idle).nohz_delay = 1; __get_cpu_var(s390_idle).nohz_delay = 1;
index = ext_hash(code); index = ext_hash(ext_code.code);
rcu_read_lock(); rcu_read_lock();
list_for_each_entry_rcu(p, &ext_int_hash[index], entry) list_for_each_entry_rcu(p, &ext_int_hash[index], entry)
if (likely(p->code == code)) if (likely(p->code == ext_code.code))
p->handler(ext_int_code, param32, param64); p->handler(ext_code, param32, param64);
rcu_read_unlock(); rcu_read_unlock();
irq_exit(); irq_exit();
set_irq_regs(old_regs); set_irq_regs(old_regs);
......
...@@ -434,14 +434,14 @@ void smp_stop_cpu(void) ...@@ -434,14 +434,14 @@ void smp_stop_cpu(void)
* This is the main routine where commands issued by other * This is the main routine where commands issued by other
* cpus are handled. * cpus are handled.
*/ */
static void do_ext_call_interrupt(unsigned int ext_int_code, static void do_ext_call_interrupt(struct ext_code ext_code,
unsigned int param32, unsigned long param64) unsigned int param32, unsigned long param64)
{ {
unsigned long bits; unsigned long bits;
int cpu; int cpu;
cpu = smp_processor_id(); cpu = smp_processor_id();
if ((ext_int_code & 0xffff) == 0x1202) if (ext_code.code == 0x1202)
kstat_cpu(cpu).irqs[EXTINT_EXC]++; kstat_cpu(cpu).irqs[EXTINT_EXC]++;
else else
kstat_cpu(cpu).irqs[EXTINT_EMS]++; kstat_cpu(cpu).irqs[EXTINT_EMS]++;
......
...@@ -165,7 +165,7 @@ void init_cpu_timer(void) ...@@ -165,7 +165,7 @@ void init_cpu_timer(void)
__ctl_set_bit(0, 4); __ctl_set_bit(0, 4);
} }
static void clock_comparator_interrupt(unsigned int ext_int_code, static void clock_comparator_interrupt(struct ext_code ext_code,
unsigned int param32, unsigned int param32,
unsigned long param64) unsigned long param64)
{ {
...@@ -177,7 +177,7 @@ static void clock_comparator_interrupt(unsigned int ext_int_code, ...@@ -177,7 +177,7 @@ static void clock_comparator_interrupt(unsigned int ext_int_code,
static void etr_timing_alert(struct etr_irq_parm *); static void etr_timing_alert(struct etr_irq_parm *);
static void stp_timing_alert(struct stp_irq_parm *); static void stp_timing_alert(struct stp_irq_parm *);
static void timing_alert_interrupt(unsigned int ext_int_code, static void timing_alert_interrupt(struct ext_code ext_code,
unsigned int param32, unsigned long param64) unsigned int param32, unsigned long param64)
{ {
kstat_cpu(smp_processor_id()).irqs[EXTINT_TLA]++; kstat_cpu(smp_processor_id()).irqs[EXTINT_TLA]++;
......
...@@ -220,7 +220,7 @@ static void do_callbacks(struct list_head *cb_list) ...@@ -220,7 +220,7 @@ static void do_callbacks(struct list_head *cb_list)
/* /*
* Handler for the virtual CPU timer. * Handler for the virtual CPU timer.
*/ */
static void do_cpu_timer_interrupt(unsigned int ext_int_code, static void do_cpu_timer_interrupt(struct ext_code ext_code,
unsigned int param32, unsigned long param64) unsigned int param32, unsigned long param64)
{ {
struct vtimer_queue *vq; struct vtimer_queue *vq;
......
...@@ -532,7 +532,7 @@ void pfault_fini(void) ...@@ -532,7 +532,7 @@ void pfault_fini(void)
static DEFINE_SPINLOCK(pfault_lock); static DEFINE_SPINLOCK(pfault_lock);
static LIST_HEAD(pfault_list); static LIST_HEAD(pfault_list);
static void pfault_interrupt(unsigned int ext_int_code, static void pfault_interrupt(struct ext_code ext_code,
unsigned int param32, unsigned long param64) unsigned int param32, unsigned long param64)
{ {
struct task_struct *tsk; struct task_struct *tsk;
...@@ -545,7 +545,7 @@ static void pfault_interrupt(unsigned int ext_int_code, ...@@ -545,7 +545,7 @@ static void pfault_interrupt(unsigned int ext_int_code,
* in the 'cpu address' field associated with the * in the 'cpu address' field associated with the
* external interrupt. * external interrupt.
*/ */
subcode = ext_int_code >> 16; subcode = ext_code.subcode;
if ((subcode & 0xff00) != __SUBCODE_MASK) if ((subcode & 0xff00) != __SUBCODE_MASK)
return; return;
kstat_cpu(smp_processor_id()).irqs[EXTINT_PFL]++; kstat_cpu(smp_processor_id()).irqs[EXTINT_PFL]++;
......
...@@ -233,7 +233,7 @@ static inline unsigned long *trailer_entry_ptr(unsigned long v) ...@@ -233,7 +233,7 @@ static inline unsigned long *trailer_entry_ptr(unsigned long v)
} }
/* prototypes for external interrupt handler and worker */ /* prototypes for external interrupt handler and worker */
static void hws_ext_handler(unsigned int ext_int_code, static void hws_ext_handler(struct ext_code ext_code,
unsigned int param32, unsigned long param64); unsigned int param32, unsigned long param64);
static void worker(struct work_struct *work); static void worker(struct work_struct *work);
...@@ -673,7 +673,7 @@ int hwsampler_activate(unsigned int cpu) ...@@ -673,7 +673,7 @@ int hwsampler_activate(unsigned int cpu)
return rc; return rc;
} }
static void hws_ext_handler(unsigned int ext_int_code, static void hws_ext_handler(struct ext_code ext_code,
unsigned int param32, unsigned long param64) unsigned int param32, unsigned long param64)
{ {
struct hws_cpu_buffer *cb; struct hws_cpu_buffer *cb;
......
...@@ -229,7 +229,7 @@ dasd_diag_term_IO(struct dasd_ccw_req * cqr) ...@@ -229,7 +229,7 @@ dasd_diag_term_IO(struct dasd_ccw_req * cqr)
} }
/* Handle external interruption. */ /* Handle external interruption. */
static void dasd_ext_handler(unsigned int ext_int_code, static void dasd_ext_handler(struct ext_code ext_code,
unsigned int param32, unsigned long param64) unsigned int param32, unsigned long param64)
{ {
struct dasd_ccw_req *cqr, *next; struct dasd_ccw_req *cqr, *next;
...@@ -239,7 +239,7 @@ static void dasd_ext_handler(unsigned int ext_int_code, ...@@ -239,7 +239,7 @@ static void dasd_ext_handler(unsigned int ext_int_code,
addr_t ip; addr_t ip;
int rc; int rc;
switch (ext_int_code >> 24) { switch (ext_code.subcode >> 8) {
case DASD_DIAG_CODE_31BIT: case DASD_DIAG_CODE_31BIT:
ip = (addr_t) param32; ip = (addr_t) param32;
break; break;
...@@ -280,7 +280,7 @@ static void dasd_ext_handler(unsigned int ext_int_code, ...@@ -280,7 +280,7 @@ static void dasd_ext_handler(unsigned int ext_int_code,
cqr->stopclk = get_clock(); cqr->stopclk = get_clock();
expires = 0; expires = 0;
if ((ext_int_code & 0xff0000) == 0) { if ((ext_code.subcode & 0xff) == 0) {
cqr->status = DASD_CQR_SUCCESS; cqr->status = DASD_CQR_SUCCESS;
/* Start first request on queue if possible -> fast_io. */ /* Start first request on queue if possible -> fast_io. */
if (!list_empty(&device->ccw_queue)) { if (!list_empty(&device->ccw_queue)) {
...@@ -296,7 +296,7 @@ static void dasd_ext_handler(unsigned int ext_int_code, ...@@ -296,7 +296,7 @@ static void dasd_ext_handler(unsigned int ext_int_code,
cqr->status = DASD_CQR_QUEUED; cqr->status = DASD_CQR_QUEUED;
DBF_DEV_EVENT(DBF_DEBUG, device, "interrupt status for " DBF_DEV_EVENT(DBF_DEBUG, device, "interrupt status for "
"request %p was %d (%d retries left)", cqr, "request %p was %d (%d retries left)", cqr,
(ext_int_code >> 16) & 0xff, cqr->retries); ext_code.subcode & 0xff, cqr->retries);
dasd_diag_erp(device); dasd_diag_erp(device);
} }
......
...@@ -393,7 +393,7 @@ __sclp_find_req(u32 sccb) ...@@ -393,7 +393,7 @@ __sclp_find_req(u32 sccb)
/* Handler for external interruption. Perform request post-processing. /* Handler for external interruption. Perform request post-processing.
* Prepare read event data request if necessary. Start processing of next * Prepare read event data request if necessary. Start processing of next
* request on queue. */ * request on queue. */
static void sclp_interrupt_handler(unsigned int ext_int_code, static void sclp_interrupt_handler(struct ext_code ext_code,
unsigned int param32, unsigned long param64) unsigned int param32, unsigned long param64)
{ {
struct sclp_req *req; struct sclp_req *req;
...@@ -818,7 +818,7 @@ EXPORT_SYMBOL(sclp_reactivate); ...@@ -818,7 +818,7 @@ EXPORT_SYMBOL(sclp_reactivate);
/* Handler for external interruption used during initialization. Modify /* Handler for external interruption used during initialization. Modify
* request state to done. */ * request state to done. */
static void sclp_check_handler(unsigned int ext_int_code, static void sclp_check_handler(struct ext_code ext_code,
unsigned int param32, unsigned long param64) unsigned int param32, unsigned long param64)
{ {
u32 finished_sccb; u32 finished_sccb;
......
...@@ -380,15 +380,13 @@ static void hotplug_devices(struct work_struct *dummy) ...@@ -380,15 +380,13 @@ static void hotplug_devices(struct work_struct *dummy)
/* /*
* we emulate the request_irq behaviour on top of s390 extints * we emulate the request_irq behaviour on top of s390 extints
*/ */
static void kvm_extint_handler(unsigned int ext_int_code, static void kvm_extint_handler(struct ext_code ext_code,
unsigned int param32, unsigned long param64) unsigned int param32, unsigned long param64)
{ {
struct virtqueue *vq; struct virtqueue *vq;
u16 subcode;
u32 param; u32 param;
subcode = ext_int_code >> 16; if ((ext_code.subcode & 0xff00) != VIRTIO_SUBCODE_64)
if ((subcode & 0xff00) != VIRTIO_SUBCODE_64)
return; return;
kstat_cpu(smp_processor_id()).irqs[EXTINT_VRT]++; kstat_cpu(smp_processor_id()).irqs[EXTINT_VRT]++;
......
...@@ -1800,7 +1800,7 @@ static void iucv_work_fn(struct work_struct *work) ...@@ -1800,7 +1800,7 @@ static void iucv_work_fn(struct work_struct *work)
* Handles external interrupts coming in from CP. * Handles external interrupts coming in from CP.
* Places the interrupt buffer on a queue and schedules iucv_tasklet_fn(). * Places the interrupt buffer on a queue and schedules iucv_tasklet_fn().
*/ */
static void iucv_external_interrupt(unsigned int ext_int_code, static void iucv_external_interrupt(struct ext_code ext_code,
unsigned int param32, unsigned long param64) unsigned int param32, unsigned long param64)
{ {
struct iucv_irq_data *p; struct iucv_irq_data *p;
......
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