diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2012-05-09 10:27:36 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2012-05-16 08:42:38 -0400 |
commit | b603d258a43b4e7339660bdd3b5c25eacd603e54 (patch) | |
tree | d6bf2fb403540be8e48e22dc85fb5587d7567d9e /drivers/s390/cio | |
parent | 0de9db37f0dff3bda21b3650ba60a21d3fe70df2 (diff) |
s390: remove superfluous tpi from wait_cons_dev
wait_cons_dev waits for a particular subchannel to complete an I/O.
It is not necessary to use tpi to get the subchannel id as it is
already known. This avoids changes to the interrupt subclass mask
and allows to remove the lock & unlock of the subchannel lock.
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio')
-rw-r--r-- | drivers/s390/cio/cio.c | 73 |
1 files changed, 19 insertions, 54 deletions
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index a49c46c91983..a6ddaed8793d 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
@@ -656,51 +656,34 @@ static struct io_subchannel_private console_priv; | |||
656 | static int console_subchannel_in_use; | 656 | static int console_subchannel_in_use; |
657 | 657 | ||
658 | /* | 658 | /* |
659 | * Use cio_tpi to get a pending interrupt and call the interrupt handler. | 659 | * Use cio_tsch to update the subchannel status and call the interrupt handler |
660 | * Return non-zero if an interrupt was processed, zero otherwise. | 660 | * if status had been pending. Called with the console_subchannel lock. |
661 | */ | 661 | */ |
662 | static int cio_tpi(void) | 662 | static void cio_tsch(struct subchannel *sch) |
663 | { | 663 | { |
664 | struct tpi_info *tpi_info; | ||
665 | struct subchannel *sch; | ||
666 | struct irb *irb; | 664 | struct irb *irb; |
667 | int irq_context; | 665 | int irq_context; |
668 | 666 | ||
669 | tpi_info = (struct tpi_info *)&S390_lowcore.subchannel_id; | ||
670 | if (tpi(NULL) != 1) | ||
671 | return 0; | ||
672 | kstat_cpu(smp_processor_id()).irqs[IO_INTERRUPT]++; | ||
673 | if (tpi_info->adapter_IO) { | ||
674 | do_adapter_IO(tpi_info->isc); | ||
675 | return 1; | ||
676 | } | ||
677 | irb = (struct irb *)&S390_lowcore.irb; | 667 | irb = (struct irb *)&S390_lowcore.irb; |
678 | /* Store interrupt response block to lowcore. */ | 668 | /* Store interrupt response block to lowcore. */ |
679 | if (tsch(tpi_info->schid, irb) != 0) { | 669 | if (tsch(sch->schid, irb) != 0) |
680 | /* Not status pending or not operational. */ | 670 | /* Not status pending or not operational. */ |
681 | kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; | 671 | return; |
682 | return 1; | 672 | memcpy(&sch->schib.scsw, &irb->scsw, sizeof(union scsw)); |
683 | } | 673 | /* Call interrupt handler with updated status. */ |
684 | sch = (struct subchannel *)(unsigned long)tpi_info->intparm; | ||
685 | if (!sch) { | ||
686 | kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; | ||
687 | return 1; | ||
688 | } | ||
689 | irq_context = in_interrupt(); | 674 | irq_context = in_interrupt(); |
690 | if (!irq_context) | 675 | if (!irq_context) { |
691 | local_bh_disable(); | 676 | local_bh_disable(); |
692 | irq_enter(); | 677 | irq_enter(); |
693 | spin_lock(sch->lock); | 678 | } |
694 | memcpy(&sch->schib.scsw, &irb->scsw, sizeof(union scsw)); | ||
695 | if (sch->driver && sch->driver->irq) | 679 | if (sch->driver && sch->driver->irq) |
696 | sch->driver->irq(sch); | 680 | sch->driver->irq(sch); |
697 | else | 681 | else |
698 | kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; | 682 | kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; |
699 | spin_unlock(sch->lock); | 683 | if (!irq_context) { |
700 | irq_exit(); | 684 | irq_exit(); |
701 | if (!irq_context) | ||
702 | _local_bh_enable(); | 685 | _local_bh_enable(); |
703 | return 1; | 686 | } |
704 | } | 687 | } |
705 | 688 | ||
706 | void *cio_get_console_priv(void) | 689 | void *cio_get_console_priv(void) |
@@ -712,34 +695,16 @@ void *cio_get_console_priv(void) | |||
712 | * busy wait for the next interrupt on the console | 695 | * busy wait for the next interrupt on the console |
713 | */ | 696 | */ |
714 | void wait_cons_dev(void) | 697 | void wait_cons_dev(void) |
715 | __releases(console_subchannel.lock) | ||
716 | __acquires(console_subchannel.lock) | ||
717 | { | 698 | { |
718 | unsigned long cr6 __attribute__ ((aligned (8))); | ||
719 | unsigned long save_cr6 __attribute__ ((aligned (8))); | ||
720 | |||
721 | /* | ||
722 | * before entering the spinlock we may already have | ||
723 | * processed the interrupt on a different CPU... | ||
724 | */ | ||
725 | if (!console_subchannel_in_use) | 699 | if (!console_subchannel_in_use) |
726 | return; | 700 | return; |
727 | 701 | ||
728 | /* disable all but the console isc */ | 702 | while (1) { |
729 | __ctl_store (save_cr6, 6, 6); | 703 | cio_tsch(&console_subchannel); |
730 | cr6 = 1UL << (31 - CONSOLE_ISC); | 704 | if (console_subchannel.schib.scsw.cmd.actl == 0) |
731 | __ctl_load (cr6, 6, 6); | 705 | break; |
732 | 706 | udelay_simple(100); | |
733 | do { | 707 | } |
734 | spin_unlock(console_subchannel.lock); | ||
735 | if (!cio_tpi()) | ||
736 | cpu_relax(); | ||
737 | spin_lock(console_subchannel.lock); | ||
738 | } while (console_subchannel.schib.scsw.cmd.actl != 0); | ||
739 | /* | ||
740 | * restore previous isc value | ||
741 | */ | ||
742 | __ctl_load (save_cr6, 6, 6); | ||
743 | } | 708 | } |
744 | 709 | ||
745 | static int | 710 | static int |