aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorMichael Holzheu <holzheu@de.ibm.com>2006-12-15 11:18:22 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2006-12-15 11:18:22 -0500
commita45e14148fb34175cba042df8979e7982758635f (patch)
tree10add976d1291f4172e95aea60e2c44594b9813d /drivers/s390
parentb3c14d0bfd1739b930f26df90552a4d8cdcca0a6 (diff)
[S390] Fix reboot hang on LPARs
Reboot hangs on LPARs without diag308 support. The reason for this is, that before the reboot is done, the channel subsystem is shut down. During the reset on each possible subchannel a "store subchannel" is done. This operation can end in a program check interruption, if the specified subchannel set is not implemented by the hardware. During the reset, currently we do not have a program check handler, which leads to the described kernel bug. We install now a new program check handler for the reboot code to fix this problem. Signed-off-by: Michael Holzheu <holzheu@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/cio/cio.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 7835a714a405..3a403f195cf8 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -871,11 +871,32 @@ __clear_subchannel_easy(struct subchannel_id schid)
871 return -EBUSY; 871 return -EBUSY;
872} 872}
873 873
874static int pgm_check_occured;
875
876static void cio_reset_pgm_check_handler(void)
877{
878 pgm_check_occured = 1;
879}
880
881static int stsch_reset(struct subchannel_id schid, volatile struct schib *addr)
882{
883 int rc;
884
885 pgm_check_occured = 0;
886 s390_reset_pgm_handler = cio_reset_pgm_check_handler;
887 rc = stsch(schid, addr);
888 s390_reset_pgm_handler = NULL;
889 if (pgm_check_occured)
890 return -EIO;
891 else
892 return rc;
893}
894
874static int __shutdown_subchannel_easy(struct subchannel_id schid, void *data) 895static int __shutdown_subchannel_easy(struct subchannel_id schid, void *data)
875{ 896{
876 struct schib schib; 897 struct schib schib;
877 898
878 if (stsch_err(schid, &schib)) 899 if (stsch_reset(schid, &schib))
879 return -ENXIO; 900 return -ENXIO;
880 if (!schib.pmcw.ena) 901 if (!schib.pmcw.ena)
881 return 0; 902 return 0;
@@ -972,7 +993,7 @@ static int __reipl_subchannel_match(struct subchannel_id schid, void *data)
972 struct schib schib; 993 struct schib schib;
973 struct sch_match_id *match_id = data; 994 struct sch_match_id *match_id = data;
974 995
975 if (stsch_err(schid, &schib)) 996 if (stsch_reset(schid, &schib))
976 return -ENXIO; 997 return -ENXIO;
977 if (schib.pmcw.dnv && 998 if (schib.pmcw.dnv &&
978 (schib.pmcw.dev == match_id->devid.devno) && 999 (schib.pmcw.dev == match_id->devid.devno) &&