diff options
author | Frank Munzert <munzert@de.ibm.com> | 2009-03-26 10:23:43 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2009-03-26 10:24:03 -0400 |
commit | 099b765139929efdcf232f8870804accf8c4cdc5 (patch) | |
tree | 9869bb629def6f49d5d3b82e8e0b301cabbc1b8c /arch/s390/kernel/ipl.c | |
parent | d7fd5f1e3b195a8232b3ed768ac2809ddce8ca46 (diff) |
[S390] Automatic IPL after dump
Provide new shutdown action "dump_reipl" for automatic ipl after dump.
Signed-off-by: Frank Munzert <munzert@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel/ipl.c')
-rw-r--r-- | arch/s390/kernel/ipl.c | 56 |
1 files changed, 52 insertions, 4 deletions
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 2dcf590faba6..5663c1f8e46a 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c | |||
@@ -56,13 +56,14 @@ struct shutdown_trigger { | |||
56 | }; | 56 | }; |
57 | 57 | ||
58 | /* | 58 | /* |
59 | * Five shutdown action types are supported: | 59 | * The following shutdown action types are supported: |
60 | */ | 60 | */ |
61 | #define SHUTDOWN_ACTION_IPL_STR "ipl" | 61 | #define SHUTDOWN_ACTION_IPL_STR "ipl" |
62 | #define SHUTDOWN_ACTION_REIPL_STR "reipl" | 62 | #define SHUTDOWN_ACTION_REIPL_STR "reipl" |
63 | #define SHUTDOWN_ACTION_DUMP_STR "dump" | 63 | #define SHUTDOWN_ACTION_DUMP_STR "dump" |
64 | #define SHUTDOWN_ACTION_VMCMD_STR "vmcmd" | 64 | #define SHUTDOWN_ACTION_VMCMD_STR "vmcmd" |
65 | #define SHUTDOWN_ACTION_STOP_STR "stop" | 65 | #define SHUTDOWN_ACTION_STOP_STR "stop" |
66 | #define SHUTDOWN_ACTION_DUMP_REIPL_STR "dump_reipl" | ||
66 | 67 | ||
67 | struct shutdown_action { | 68 | struct shutdown_action { |
68 | char *name; | 69 | char *name; |
@@ -146,6 +147,7 @@ static enum ipl_method reipl_method = REIPL_METHOD_DEFAULT; | |||
146 | static struct ipl_parameter_block *reipl_block_fcp; | 147 | static struct ipl_parameter_block *reipl_block_fcp; |
147 | static struct ipl_parameter_block *reipl_block_ccw; | 148 | static struct ipl_parameter_block *reipl_block_ccw; |
148 | static struct ipl_parameter_block *reipl_block_nss; | 149 | static struct ipl_parameter_block *reipl_block_nss; |
150 | static struct ipl_parameter_block *reipl_block_actual; | ||
149 | 151 | ||
150 | static int dump_capabilities = DUMP_TYPE_NONE; | 152 | static int dump_capabilities = DUMP_TYPE_NONE; |
151 | static enum dump_type dump_type = DUMP_TYPE_NONE; | 153 | static enum dump_type dump_type = DUMP_TYPE_NONE; |
@@ -835,6 +837,7 @@ static int reipl_set_type(enum ipl_type type) | |||
835 | reipl_method = REIPL_METHOD_CCW_VM; | 837 | reipl_method = REIPL_METHOD_CCW_VM; |
836 | else | 838 | else |
837 | reipl_method = REIPL_METHOD_CCW_CIO; | 839 | reipl_method = REIPL_METHOD_CCW_CIO; |
840 | reipl_block_actual = reipl_block_ccw; | ||
838 | break; | 841 | break; |
839 | case IPL_TYPE_FCP: | 842 | case IPL_TYPE_FCP: |
840 | if (diag308_set_works) | 843 | if (diag308_set_works) |
@@ -843,6 +846,7 @@ static int reipl_set_type(enum ipl_type type) | |||
843 | reipl_method = REIPL_METHOD_FCP_RO_VM; | 846 | reipl_method = REIPL_METHOD_FCP_RO_VM; |
844 | else | 847 | else |
845 | reipl_method = REIPL_METHOD_FCP_RO_DIAG; | 848 | reipl_method = REIPL_METHOD_FCP_RO_DIAG; |
849 | reipl_block_actual = reipl_block_fcp; | ||
846 | break; | 850 | break; |
847 | case IPL_TYPE_FCP_DUMP: | 851 | case IPL_TYPE_FCP_DUMP: |
848 | reipl_method = REIPL_METHOD_FCP_DUMP; | 852 | reipl_method = REIPL_METHOD_FCP_DUMP; |
@@ -852,6 +856,7 @@ static int reipl_set_type(enum ipl_type type) | |||
852 | reipl_method = REIPL_METHOD_NSS_DIAG; | 856 | reipl_method = REIPL_METHOD_NSS_DIAG; |
853 | else | 857 | else |
854 | reipl_method = REIPL_METHOD_NSS; | 858 | reipl_method = REIPL_METHOD_NSS; |
859 | reipl_block_actual = reipl_block_nss; | ||
855 | break; | 860 | break; |
856 | case IPL_TYPE_UNKNOWN: | 861 | case IPL_TYPE_UNKNOWN: |
857 | reipl_method = REIPL_METHOD_DEFAULT; | 862 | reipl_method = REIPL_METHOD_DEFAULT; |
@@ -1332,6 +1337,48 @@ static struct shutdown_action __refdata dump_action = { | |||
1332 | .init = dump_init, | 1337 | .init = dump_init, |
1333 | }; | 1338 | }; |
1334 | 1339 | ||
1340 | static void dump_reipl_run(struct shutdown_trigger *trigger) | ||
1341 | { | ||
1342 | preempt_disable(); | ||
1343 | /* | ||
1344 | * Bypass dynamic address translation (DAT) when storing IPL parameter | ||
1345 | * information block address and checksum into the prefix area | ||
1346 | * (corresponding to absolute addresses 0-8191). | ||
1347 | * When enhanced DAT applies and the STE format control in one, | ||
1348 | * the absolute address is formed without prefixing. In this case a | ||
1349 | * normal store (stg/st) into the prefix area would no more match to | ||
1350 | * absolute addresses 0-8191. | ||
1351 | */ | ||
1352 | #ifdef CONFIG_64BIT | ||
1353 | asm volatile("sturg %0,%1" | ||
1354 | :: "a" ((unsigned long) reipl_block_actual), | ||
1355 | "a" (&lowcore_ptr[smp_processor_id()]->ipib)); | ||
1356 | #else | ||
1357 | asm volatile("stura %0,%1" | ||
1358 | :: "a" ((unsigned long) reipl_block_actual), | ||
1359 | "a" (&lowcore_ptr[smp_processor_id()]->ipib)); | ||
1360 | #endif | ||
1361 | asm volatile("stura %0,%1" | ||
1362 | :: "a" (cksm(reipl_block_actual, reipl_block_actual->hdr.len)), | ||
1363 | "a" (&lowcore_ptr[smp_processor_id()]->ipib_checksum)); | ||
1364 | preempt_enable(); | ||
1365 | dump_run(trigger); | ||
1366 | } | ||
1367 | |||
1368 | static int __init dump_reipl_init(void) | ||
1369 | { | ||
1370 | if (!diag308_set_works) | ||
1371 | return -EOPNOTSUPP; | ||
1372 | else | ||
1373 | return 0; | ||
1374 | } | ||
1375 | |||
1376 | static struct shutdown_action __refdata dump_reipl_action = { | ||
1377 | .name = SHUTDOWN_ACTION_DUMP_REIPL_STR, | ||
1378 | .fn = dump_reipl_run, | ||
1379 | .init = dump_reipl_init, | ||
1380 | }; | ||
1381 | |||
1335 | /* | 1382 | /* |
1336 | * vmcmd shutdown action: Trigger vm command on shutdown. | 1383 | * vmcmd shutdown action: Trigger vm command on shutdown. |
1337 | */ | 1384 | */ |
@@ -1421,7 +1468,8 @@ static struct shutdown_action stop_action = {SHUTDOWN_ACTION_STOP_STR, | |||
1421 | /* action list */ | 1468 | /* action list */ |
1422 | 1469 | ||
1423 | static struct shutdown_action *shutdown_actions_list[] = { | 1470 | static struct shutdown_action *shutdown_actions_list[] = { |
1424 | &ipl_action, &reipl_action, &dump_action, &vmcmd_action, &stop_action}; | 1471 | &ipl_action, &reipl_action, &dump_reipl_action, &dump_action, |
1472 | &vmcmd_action, &stop_action}; | ||
1425 | #define SHUTDOWN_ACTIONS_COUNT (sizeof(shutdown_actions_list) / sizeof(void *)) | 1473 | #define SHUTDOWN_ACTIONS_COUNT (sizeof(shutdown_actions_list) / sizeof(void *)) |
1426 | 1474 | ||
1427 | /* | 1475 | /* |
@@ -1434,11 +1482,11 @@ static int set_trigger(const char *buf, struct shutdown_trigger *trigger, | |||
1434 | size_t len) | 1482 | size_t len) |
1435 | { | 1483 | { |
1436 | int i; | 1484 | int i; |
1485 | |||
1437 | for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) { | 1486 | for (i = 0; i < SHUTDOWN_ACTIONS_COUNT; i++) { |
1438 | if (!shutdown_actions_list[i]) | 1487 | if (!shutdown_actions_list[i]) |
1439 | continue; | 1488 | continue; |
1440 | if (strncmp(buf, shutdown_actions_list[i]->name, | 1489 | if (sysfs_streq(buf, shutdown_actions_list[i]->name)) { |
1441 | strlen(shutdown_actions_list[i]->name)) == 0) { | ||
1442 | trigger->action = shutdown_actions_list[i]; | 1490 | trigger->action = shutdown_actions_list[i]; |
1443 | return len; | 1491 | return len; |
1444 | } | 1492 | } |