aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio/cio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/cio/cio.c')
-rw-r--r--drivers/s390/cio/cio.c79
1 files changed, 43 insertions, 36 deletions
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 396bada65f86..3eb6cb608fc9 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -691,7 +691,22 @@ wait_cons_dev (void)
691} 691}
692 692
693static int 693static int
694cio_console_irq(void) 694cio_test_for_console(struct subchannel_id schid, void *data)
695{
696 if (stsch(schid, &console_subchannel.schib) != 0)
697 return -ENXIO;
698 if (console_subchannel.schib.pmcw.dnv &&
699 console_subchannel.schib.pmcw.dev ==
700 console_devno) {
701 console_irq = schid.sch_no;
702 return 1; /* found */
703 }
704 return 0;
705}
706
707
708static int
709cio_get_console_sch_no(void)
695{ 710{
696 struct subchannel_id schid; 711 struct subchannel_id schid;
697 712
@@ -705,16 +720,7 @@ cio_console_irq(void)
705 console_devno = console_subchannel.schib.pmcw.dev; 720 console_devno = console_subchannel.schib.pmcw.dev;
706 } else if (console_devno != -1) { 721 } else if (console_devno != -1) {
707 /* At least the console device number is known. */ 722 /* At least the console device number is known. */
708 do { 723 for_each_subchannel(cio_test_for_console, NULL);
709 if (stsch(schid, &console_subchannel.schib) != 0)
710 break;
711 if (console_subchannel.schib.pmcw.dnv &&
712 console_subchannel.schib.pmcw.dev ==
713 console_devno) {
714 console_irq = schid.sch_no;
715 break;
716 }
717 } while (schid.sch_no++ < __MAX_SUBCHANNEL);
718 if (console_irq == -1) 724 if (console_irq == -1)
719 return -1; 725 return -1;
720 } else { 726 } else {
@@ -730,19 +736,19 @@ cio_console_irq(void)
730struct subchannel * 736struct subchannel *
731cio_probe_console(void) 737cio_probe_console(void)
732{ 738{
733 int irq, ret; 739 int sch_no, ret;
734 struct subchannel_id schid; 740 struct subchannel_id schid;
735 741
736 if (xchg(&console_subchannel_in_use, 1) != 0) 742 if (xchg(&console_subchannel_in_use, 1) != 0)
737 return ERR_PTR(-EBUSY); 743 return ERR_PTR(-EBUSY);
738 irq = cio_console_irq(); 744 sch_no = cio_get_console_sch_no();
739 if (irq == -1) { 745 if (sch_no == -1) {
740 console_subchannel_in_use = 0; 746 console_subchannel_in_use = 0;
741 return ERR_PTR(-ENODEV); 747 return ERR_PTR(-ENODEV);
742 } 748 }
743 memset(&console_subchannel, 0, sizeof(struct subchannel)); 749 memset(&console_subchannel, 0, sizeof(struct subchannel));
744 init_subchannel_id(&schid); 750 init_subchannel_id(&schid);
745 schid.sch_no = irq; 751 schid.sch_no = sch_no;
746 ret = cio_validate_subchannel(&console_subchannel, schid); 752 ret = cio_validate_subchannel(&console_subchannel, schid);
747 if (ret) { 753 if (ret) {
748 console_subchannel_in_use = 0; 754 console_subchannel_in_use = 0;
@@ -830,32 +836,33 @@ __clear_subchannel_easy(struct subchannel_id schid)
830} 836}
831 837
832extern void do_reipl(unsigned long devno); 838extern void do_reipl(unsigned long devno);
839static int
840__shutdown_subchannel_easy(struct subchannel_id schid, void *data)
841{
842 struct schib schib;
843
844 if (stsch(schid, &schib))
845 return -ENXIO;
846 if (!schib.pmcw.ena)
847 return 0;
848 switch(__disable_subchannel_easy(schid, &schib)) {
849 case 0:
850 case -ENODEV:
851 break;
852 default: /* -EBUSY */
853 if (__clear_subchannel_easy(schid))
854 break; /* give up... */
855 stsch(schid, &schib);
856 __disable_subchannel_easy(schid, &schib);
857 }
858 return 0;
859}
833 860
834/* Clear all subchannels. */
835void 861void
836clear_all_subchannels(void) 862clear_all_subchannels(void)
837{ 863{
838 struct subchannel_id schid;
839
840 local_irq_disable(); 864 local_irq_disable();
841 init_subchannel_id(&schid); 865 for_each_subchannel(__shutdown_subchannel_easy, NULL);
842 do {
843 struct schib schib;
844 if (stsch(schid, &schib))
845 break; /* break out of the loop */
846 if (!schib.pmcw.ena)
847 continue;
848 switch(__disable_subchannel_easy(schid, &schib)) {
849 case 0:
850 case -ENODEV:
851 break;
852 default: /* -EBUSY */
853 if (__clear_subchannel_easy(schid))
854 break; /* give up... jump out of switch */
855 stsch(schid, &schib);
856 __disable_subchannel_easy(schid, &schib);
857 }
858 } while (schid.sch_no++ < __MAX_SUBCHANNEL);
859} 866}
860 867
861/* Make sure all subchannels are quiet before we re-ipl an lpar. */ 868/* Make sure all subchannels are quiet before we re-ipl an lpar. */