diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/s390/cio/airq.c | 21 | ||||
-rw-r--r-- | drivers/s390/cio/cio.c | 46 | ||||
-rw-r--r-- | drivers/s390/cio/cio.h | 3 |
3 files changed, 42 insertions, 28 deletions
diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c index 6ead6d07644..d028fd800c9 100644 --- a/drivers/s390/cio/airq.c +++ b/drivers/s390/cio/airq.c @@ -81,17 +81,34 @@ void unregister_adapter_interrupt(struct airq_struct *airq) } EXPORT_SYMBOL(unregister_adapter_interrupt); -void do_adapter_IO(u8 isc) +static irqreturn_t do_airq_interrupt(int irq, void *dummy) { + struct tpi_info *tpi_info; struct airq_struct *airq; struct hlist_head *head; - head = &airq_lists[isc]; + __this_cpu_write(s390_idle.nohz_delay, 1); + tpi_info = (struct tpi_info *) &get_irq_regs()->int_code; + head = &airq_lists[tpi_info->isc]; rcu_read_lock(); hlist_for_each_entry_rcu(airq, head, list) if ((*airq->lsi_ptr & airq->lsi_mask) != 0) airq->handler(airq); rcu_read_unlock(); + + return IRQ_HANDLED; +} + +static struct irqaction airq_interrupt = { + .name = "AIO", + .handler = do_airq_interrupt, +}; + +void __init init_airq_interrupts(void) +{ + irq_set_chip_and_handler(THIN_INTERRUPT, + &dummy_irq_chip, handle_percpu_irq); + setup_irq(THIN_INTERRUPT, &airq_interrupt); } /** diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 4eeb4a6bf20..d7da67a31c7 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c @@ -561,37 +561,23 @@ out: } /* - * do_IRQ() handles all normal I/O device IRQ's (the special - * SMP cross-CPU interrupts have their own specific - * handlers). - * + * do_cio_interrupt() handles all normal I/O device IRQ's */ -void __irq_entry do_IRQ(struct pt_regs *regs) +static irqreturn_t do_cio_interrupt(int irq, void *dummy) { - struct tpi_info *tpi_info = (struct tpi_info *) ®s->int_code; + struct tpi_info *tpi_info; struct subchannel *sch; struct irb *irb; - struct pt_regs *old_regs; - old_regs = set_irq_regs(regs); - irq_enter(); __this_cpu_write(s390_idle.nohz_delay, 1); - if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) - /* Serve timer interrupts first. */ - clock_comparator_work(); - - kstat_incr_irqs_this_cpu(IO_INTERRUPT, NULL); + tpi_info = (struct tpi_info *) &get_irq_regs()->int_code; irb = (struct irb *) &S390_lowcore.irb; - if (tpi_info->adapter_IO) { - do_adapter_IO(tpi_info->isc); - goto out; - } sch = (struct subchannel *)(unsigned long) tpi_info->intparm; if (!sch) { /* Clear pending interrupt condition. */ inc_irq_stat(IRQIO_CIO); tsch(tpi_info->schid, irb); - goto out; + return IRQ_HANDLED; } spin_lock(sch->lock); /* Store interrupt response block to lowcore. */ @@ -606,9 +592,23 @@ void __irq_entry do_IRQ(struct pt_regs *regs) } else inc_irq_stat(IRQIO_CIO); spin_unlock(sch->lock); -out: - irq_exit(); - set_irq_regs(old_regs); + + return IRQ_HANDLED; +} + +static struct irq_desc *irq_desc_io; + +static struct irqaction io_interrupt = { + .name = "IO", + .handler = do_cio_interrupt, +}; + +void __init init_cio_interrupts(void) +{ + irq_set_chip_and_handler(IO_INTERRUPT, + &dummy_irq_chip, handle_percpu_irq); + setup_irq(IO_INTERRUPT, &io_interrupt); + irq_desc_io = irq_to_desc(IO_INTERRUPT); } #ifdef CONFIG_CCW_CONSOLE @@ -635,7 +635,7 @@ void cio_tsch(struct subchannel *sch) local_bh_disable(); irq_enter(); } - kstat_incr_irqs_this_cpu(IO_INTERRUPT, NULL); + kstat_incr_irqs_this_cpu(IO_INTERRUPT, irq_desc_io); if (sch->driver && sch->driver->irq) sch->driver->irq(sch); else diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h index d62f5e7f3cf..d42f67412bd 100644 --- a/drivers/s390/cio/cio.h +++ b/drivers/s390/cio/cio.h @@ -121,9 +121,6 @@ extern int cio_commit_config(struct subchannel *sch); int cio_tm_start_key(struct subchannel *sch, struct tcw *tcw, u8 lpm, u8 key); int cio_tm_intrg(struct subchannel *sch); -void do_adapter_IO(u8 isc); -void do_IRQ(struct pt_regs *); - /* Use with care. */ #ifdef CONFIG_CCW_CONSOLE extern struct subchannel *cio_probe_console(void); |