aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/cio/cio.c50
1 files changed, 40 insertions, 10 deletions
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 89320c1ad825..050963f15802 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -841,14 +841,26 @@ __clear_subchannel_easy(struct subchannel_id schid)
841 return -EBUSY; 841 return -EBUSY;
842} 842}
843 843
844extern void do_reipl(unsigned long devno); 844struct sch_match_id {
845static int 845 struct subchannel_id schid;
846__shutdown_subchannel_easy(struct subchannel_id schid, void *data) 846 struct ccw_dev_id devid;
847 int rc;
848};
849
850static int __shutdown_subchannel_easy_and_match(struct subchannel_id schid,
851 void *data)
847{ 852{
848 struct schib schib; 853 struct schib schib;
854 struct sch_match_id *match_id = data;
849 855
850 if (stsch_err(schid, &schib)) 856 if (stsch_err(schid, &schib))
851 return -ENXIO; 857 return -ENXIO;
858 if (match_id && schib.pmcw.dnv &&
859 (schib.pmcw.dev == match_id->devid.devno) &&
860 (schid.ssid == match_id->devid.ssid)) {
861 match_id->schid = schid;
862 match_id->rc = 0;
863 }
852 if (!schib.pmcw.ena) 864 if (!schib.pmcw.ena)
853 return 0; 865 return 0;
854 switch(__disable_subchannel_easy(schid, &schib)) { 866 switch(__disable_subchannel_easy(schid, &schib)) {
@@ -864,18 +876,36 @@ __shutdown_subchannel_easy(struct subchannel_id schid, void *data)
864 return 0; 876 return 0;
865} 877}
866 878
867void 879static int clear_all_subchannels_and_match(struct ccw_dev_id *devid,
868clear_all_subchannels(void) 880 struct subchannel_id *schid)
869{ 881{
882 struct sch_match_id match_id;
883
884 match_id.devid = *devid;
885 match_id.rc = -ENODEV;
870 local_irq_disable(); 886 local_irq_disable();
871 for_each_subchannel(__shutdown_subchannel_easy, NULL); 887 for_each_subchannel(__shutdown_subchannel_easy_and_match, &match_id);
888 if (match_id.rc == 0)
889 *schid = match_id.schid;
890 return match_id.rc;
872} 891}
873 892
893
894void clear_all_subchannels(void)
895{
896 local_irq_disable();
897 for_each_subchannel(__shutdown_subchannel_easy_and_match, NULL);
898}
899
900extern void do_reipl_asm(__u32 schid);
901
874/* Make sure all subchannels are quiet before we re-ipl an lpar. */ 902/* Make sure all subchannels are quiet before we re-ipl an lpar. */
875void 903void reipl_ccw_dev(struct ccw_dev_id *devid)
876reipl(unsigned long devno)
877{ 904{
878 clear_all_subchannels(); 905 struct subchannel_id schid;
906
907 if (clear_all_subchannels_and_match(devid, &schid))
908 panic("IPL Device not found\n");
879 cio_reset_channel_paths(); 909 cio_reset_channel_paths();
880 do_reipl(devno); 910 do_reipl_asm(*((__u32*)&schid));
881} 911}