diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2013-06-17 08:54:02 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2013-06-26 15:10:23 -0400 |
commit | 48f6b00c6e3190b786c44731b25ac124c81c2247 (patch) | |
tree | c06d6ba767544eba04a2cd47db1c303f6a35d9f7 /drivers/s390/cio | |
parent | 4bdb613ff45ef5f2848584b250f8a65f6d6c5755 (diff) |
s390/irq: store interrupt information in pt_regs
Copy the interrupt parameters from the lowcore to the pt_regs structure
in entry[64].S and reduce the arguments of the low level interrupt handler
to the pt_regs pointer only. In addition move the test-pending-interrupt
loop from do_IRQ to entry[64].S to make sure that interrupt information
is always delivered via pt_regs.
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio')
-rw-r--r-- | drivers/s390/cio/cio.c | 68 |
1 files changed, 28 insertions, 40 deletions
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 935d80b4e9ce..4eeb4a6bf207 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
@@ -568,7 +568,7 @@ out: | |||
568 | */ | 568 | */ |
569 | void __irq_entry do_IRQ(struct pt_regs *regs) | 569 | void __irq_entry do_IRQ(struct pt_regs *regs) |
570 | { | 570 | { |
571 | struct tpi_info *tpi_info; | 571 | struct tpi_info *tpi_info = (struct tpi_info *) ®s->int_code; |
572 | struct subchannel *sch; | 572 | struct subchannel *sch; |
573 | struct irb *irb; | 573 | struct irb *irb; |
574 | struct pt_regs *old_regs; | 574 | struct pt_regs *old_regs; |
@@ -579,46 +579,34 @@ void __irq_entry do_IRQ(struct pt_regs *regs) | |||
579 | if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) | 579 | if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) |
580 | /* Serve timer interrupts first. */ | 580 | /* Serve timer interrupts first. */ |
581 | clock_comparator_work(); | 581 | clock_comparator_work(); |
582 | /* | 582 | |
583 | * Get interrupt information from lowcore | 583 | kstat_incr_irqs_this_cpu(IO_INTERRUPT, NULL); |
584 | */ | 584 | irb = (struct irb *) &S390_lowcore.irb; |
585 | tpi_info = (struct tpi_info *)&S390_lowcore.subchannel_id; | 585 | if (tpi_info->adapter_IO) { |
586 | irb = (struct irb *)&S390_lowcore.irb; | 586 | do_adapter_IO(tpi_info->isc); |
587 | do { | 587 | goto out; |
588 | kstat_incr_irqs_this_cpu(IO_INTERRUPT, NULL); | 588 | } |
589 | if (tpi_info->adapter_IO) { | 589 | sch = (struct subchannel *)(unsigned long) tpi_info->intparm; |
590 | do_adapter_IO(tpi_info->isc); | 590 | if (!sch) { |
591 | continue; | 591 | /* Clear pending interrupt condition. */ |
592 | } | 592 | inc_irq_stat(IRQIO_CIO); |
593 | sch = (struct subchannel *)(unsigned long)tpi_info->intparm; | 593 | tsch(tpi_info->schid, irb); |
594 | if (!sch) { | 594 | goto out; |
595 | /* Clear pending interrupt condition. */ | 595 | } |
596 | inc_irq_stat(IRQIO_CIO); | 596 | spin_lock(sch->lock); |
597 | tsch(tpi_info->schid, irb); | 597 | /* Store interrupt response block to lowcore. */ |
598 | continue; | 598 | if (tsch(tpi_info->schid, irb) == 0) { |
599 | } | 599 | /* Keep subchannel information word up to date. */ |
600 | spin_lock(sch->lock); | 600 | memcpy (&sch->schib.scsw, &irb->scsw, sizeof (irb->scsw)); |
601 | /* Store interrupt response block to lowcore. */ | 601 | /* Call interrupt handler if there is one. */ |
602 | if (tsch(tpi_info->schid, irb) == 0) { | 602 | if (sch->driver && sch->driver->irq) |
603 | /* Keep subchannel information word up to date. */ | 603 | sch->driver->irq(sch); |
604 | memcpy (&sch->schib.scsw, &irb->scsw, | 604 | else |
605 | sizeof (irb->scsw)); | ||
606 | /* Call interrupt handler if there is one. */ | ||
607 | if (sch->driver && sch->driver->irq) | ||
608 | sch->driver->irq(sch); | ||
609 | else | ||
610 | inc_irq_stat(IRQIO_CIO); | ||
611 | } else | ||
612 | inc_irq_stat(IRQIO_CIO); | 605 | inc_irq_stat(IRQIO_CIO); |
613 | spin_unlock(sch->lock); | 606 | } else |
614 | /* | 607 | inc_irq_stat(IRQIO_CIO); |
615 | * Are more interrupts pending? | 608 | spin_unlock(sch->lock); |
616 | * If so, the tpi instruction will update the lowcore | 609 | out: |
617 | * to hold the info for the next interrupt. | ||
618 | * We don't do this for VM because a tpi drops the cpu | ||
619 | * out of the sie which costs more cycles than it saves. | ||
620 | */ | ||
621 | } while (MACHINE_IS_LPAR && tpi(NULL) != 0); | ||
622 | irq_exit(); | 610 | irq_exit(); |
623 | set_irq_regs(old_regs); | 611 | set_irq_regs(old_regs); |
624 | } | 612 | } |