aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2012-05-09 10:27:36 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2012-05-16 08:42:38 -0400
commitb603d258a43b4e7339660bdd3b5c25eacd603e54 (patch)
treed6bf2fb403540be8e48e22dc85fb5587d7567d9e /drivers/s390/cio
parent0de9db37f0dff3bda21b3650ba60a21d3fe70df2 (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.c73
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;
656static int console_subchannel_in_use; 656static 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 */
662static int cio_tpi(void) 662static 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
706void *cio_get_console_priv(void) 689void *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 */
714void wait_cons_dev(void) 697void 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
745static int 710static int