Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

+20 -55
+20 -55
drivers/s390/cio/cio.c
··· 656 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. 660 - * Return non-zero if an interrupt was processed, zero otherwise. 659 + * Use cio_tsch to update the subchannel status and call the interrupt handler 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 664 struct irb *irb; 667 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 667 irb = (struct irb *)&S390_lowcore.irb; 678 668 /* Store interrupt response block to lowcore. */ 679 - if (tsch(tpi_info->schid, irb) != 0) { 669 + if (tsch(sch->schid, irb) != 0) 680 670 /* Not status pending or not operational. */ 681 - kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; 682 - return 1; 683 - } 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(); 690 - if (!irq_context) 691 - local_bh_disable(); 692 - irq_enter(); 693 - spin_lock(sch->lock); 671 + return; 694 672 memcpy(&sch->schib.scsw, &irb->scsw, sizeof(union scsw)); 673 + /* Call interrupt handler with updated status. */ 674 + irq_context = in_interrupt(); 675 + if (!irq_context) { 676 + local_bh_disable(); 677 + irq_enter(); 678 + } 695 679 if (sch->driver && sch->driver->irq) 696 680 sch->driver->irq(sch); 697 681 else 698 682 kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; 699 - spin_unlock(sch->lock); 700 - irq_exit(); 701 - if (!irq_context) 683 + if (!irq_context) { 684 + irq_exit(); 702 685 _local_bh_enable(); 703 - return 1; 686 + } 704 687 } 705 688 706 689 void *cio_get_console_priv(void) ··· 695 712 * busy wait for the next interrupt on the console 696 713 */ 697 714 void wait_cons_dev(void) 698 - __releases(console_subchannel.lock) 699 - __acquires(console_subchannel.lock) 700 715 { 701 - unsigned long cr6 __attribute__ ((aligned (8))); 702 - unsigned long save_cr6 __attribute__ ((aligned (8))); 703 - 704 - /* 705 - * before entering the spinlock we may already have 706 - * processed the interrupt on a different CPU... 707 - */ 708 716 if (!console_subchannel_in_use) 709 717 return; 710 718 711 - /* disable all but the console isc */ 712 - __ctl_store (save_cr6, 6, 6); 713 - cr6 = 1UL << (31 - CONSOLE_ISC); 714 - __ctl_load (cr6, 6, 6); 715 - 716 - do { 717 - spin_unlock(console_subchannel.lock); 718 - if (!cio_tpi()) 719 - cpu_relax(); 720 - spin_lock(console_subchannel.lock); 721 - } while (console_subchannel.schib.scsw.cmd.actl != 0); 722 - /* 723 - * restore previous isc value 724 - */ 725 - __ctl_load (save_cr6, 6, 6); 719 + while (1) { 720 + cio_tsch(&console_subchannel); 721 + if (console_subchannel.schib.scsw.cmd.actl == 0) 722 + break; 723 + udelay_simple(100); 724 + } 726 725 } 727 726 728 727 static int