diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2009-06-16 04:30:47 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2009-06-16 04:31:20 -0400 |
commit | 4b214a0c7720bfcfaca936047a359f8859fc8424 (patch) | |
tree | 33cbc967ffd4b7a316cada0917006bd7031ccfb2 /drivers/s390/char/raw3270.c | |
parent | 6a1d96dced593bc17d7a17fdb93c99b275e71eba (diff) |
[S390] pm: con3270 power management callbacks.
Introduce the power management callbacks to the 3270 driver. On suspend
the current 3270 view is deactivated and for non-console 3270 device
the release callback is done. This disconnects the current tty /
fullscreen application from the 3270 device. On resume the current
view is reactivated, on the tty you get a fresh login.
If the system panics before the 3270 device has been resumed, the ccw
device for the 3270 console is reactivated with ccw_device_force_console.
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/char/raw3270.c')
-rw-r--r-- | drivers/s390/char/raw3270.c | 84 |
1 files changed, 73 insertions, 11 deletions
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index 0b15cf107ec9..81c151b5f0ac 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c | |||
@@ -1,11 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/char/raw3270.c | 2 | * IBM/3270 Driver - core functions. |
3 | * IBM/3270 Driver - core functions. | ||
4 | * | 3 | * |
5 | * Author(s): | 4 | * Author(s): |
6 | * Original 3270 Code for 2.4 written by Richard Hitt (UTS Global) | 5 | * Original 3270 Code for 2.4 written by Richard Hitt (UTS Global) |
7 | * Rewritten for 2.5 by Martin Schwidefsky <schwidefsky@de.ibm.com> | 6 | * Rewritten for 2.5 by Martin Schwidefsky <schwidefsky@de.ibm.com> |
8 | * -- Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation | 7 | * Copyright IBM Corp. 2003, 2009 |
9 | */ | 8 | */ |
10 | 9 | ||
11 | #include <linux/bootmem.h> | 10 | #include <linux/bootmem.h> |
@@ -61,6 +60,7 @@ struct raw3270 { | |||
61 | #define RAW3270_FLAGS_ATTN 2 /* Device sent an ATTN interrupt */ | 60 | #define RAW3270_FLAGS_ATTN 2 /* Device sent an ATTN interrupt */ |
62 | #define RAW3270_FLAGS_READY 4 /* Device is useable by views */ | 61 | #define RAW3270_FLAGS_READY 4 /* Device is useable by views */ |
63 | #define RAW3270_FLAGS_CONSOLE 8 /* Device is the console. */ | 62 | #define RAW3270_FLAGS_CONSOLE 8 /* Device is the console. */ |
63 | #define RAW3270_FLAGS_FROZEN 16 /* set if 3270 is frozen for suspend */ | ||
64 | 64 | ||
65 | /* Semaphore to protect global data of raw3270 (devices, views, etc). */ | 65 | /* Semaphore to protect global data of raw3270 (devices, views, etc). */ |
66 | static DEFINE_MUTEX(raw3270_mutex); | 66 | static DEFINE_MUTEX(raw3270_mutex); |
@@ -306,7 +306,8 @@ raw3270_start(struct raw3270_view *view, struct raw3270_request *rq) | |||
306 | 306 | ||
307 | spin_lock_irqsave(get_ccwdev_lock(view->dev->cdev), flags); | 307 | spin_lock_irqsave(get_ccwdev_lock(view->dev->cdev), flags); |
308 | rp = view->dev; | 308 | rp = view->dev; |
309 | if (!rp || rp->view != view) | 309 | if (!rp || rp->view != view || |
310 | test_bit(RAW3270_FLAGS_FROZEN, &rp->flags)) | ||
310 | rc = -EACCES; | 311 | rc = -EACCES; |
311 | else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags)) | 312 | else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags)) |
312 | rc = -ENODEV; | 313 | rc = -ENODEV; |
@@ -323,7 +324,8 @@ raw3270_start_locked(struct raw3270_view *view, struct raw3270_request *rq) | |||
323 | int rc; | 324 | int rc; |
324 | 325 | ||
325 | rp = view->dev; | 326 | rp = view->dev; |
326 | if (!rp || rp->view != view) | 327 | if (!rp || rp->view != view || |
328 | test_bit(RAW3270_FLAGS_FROZEN, &rp->flags)) | ||
327 | rc = -EACCES; | 329 | rc = -EACCES; |
328 | else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags)) | 330 | else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags)) |
329 | rc = -ENODEV; | 331 | rc = -ENODEV; |
@@ -764,7 +766,8 @@ raw3270_reset(struct raw3270_view *view) | |||
764 | int rc; | 766 | int rc; |
765 | 767 | ||
766 | rp = view->dev; | 768 | rp = view->dev; |
767 | if (!rp || rp->view != view) | 769 | if (!rp || rp->view != view || |
770 | test_bit(RAW3270_FLAGS_FROZEN, &rp->flags)) | ||
768 | rc = -EACCES; | 771 | rc = -EACCES; |
769 | else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags)) | 772 | else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags)) |
770 | rc = -ENODEV; | 773 | rc = -ENODEV; |
@@ -922,6 +925,8 @@ raw3270_activate_view(struct raw3270_view *view) | |||
922 | rc = 0; | 925 | rc = 0; |
923 | else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags)) | 926 | else if (!test_bit(RAW3270_FLAGS_READY, &rp->flags)) |
924 | rc = -ENODEV; | 927 | rc = -ENODEV; |
928 | else if (test_bit(RAW3270_FLAGS_FROZEN, &rp->flags)) | ||
929 | rc = -EACCES; | ||
925 | else { | 930 | else { |
926 | oldview = NULL; | 931 | oldview = NULL; |
927 | if (rp->view) { | 932 | if (rp->view) { |
@@ -969,7 +974,8 @@ raw3270_deactivate_view(struct raw3270_view *view) | |||
969 | list_del_init(&view->list); | 974 | list_del_init(&view->list); |
970 | list_add_tail(&view->list, &rp->view_list); | 975 | list_add_tail(&view->list, &rp->view_list); |
971 | /* Try to activate another view. */ | 976 | /* Try to activate another view. */ |
972 | if (test_bit(RAW3270_FLAGS_READY, &rp->flags)) { | 977 | if (test_bit(RAW3270_FLAGS_READY, &rp->flags) && |
978 | !test_bit(RAW3270_FLAGS_FROZEN, &rp->flags)) { | ||
973 | list_for_each_entry(view, &rp->view_list, list) { | 979 | list_for_each_entry(view, &rp->view_list, list) { |
974 | rp->view = view; | 980 | rp->view = view; |
975 | if (view->fn->activate(view) == 0) | 981 | if (view->fn->activate(view) == 0) |
@@ -1068,7 +1074,8 @@ raw3270_del_view(struct raw3270_view *view) | |||
1068 | rp->view = NULL; | 1074 | rp->view = NULL; |
1069 | } | 1075 | } |
1070 | list_del_init(&view->list); | 1076 | list_del_init(&view->list); |
1071 | if (!rp->view && test_bit(RAW3270_FLAGS_READY, &rp->flags)) { | 1077 | if (!rp->view && test_bit(RAW3270_FLAGS_READY, &rp->flags) && |
1078 | !test_bit(RAW3270_FLAGS_FROZEN, &rp->flags)) { | ||
1072 | /* Try to activate another view. */ | 1079 | /* Try to activate another view. */ |
1073 | list_for_each_entry(nv, &rp->view_list, list) { | 1080 | list_for_each_entry(nv, &rp->view_list, list) { |
1074 | if (nv->fn->activate(nv) == 0) { | 1081 | if (nv->fn->activate(nv) == 0) { |
@@ -1337,6 +1344,58 @@ raw3270_set_offline (struct ccw_device *cdev) | |||
1337 | return 0; | 1344 | return 0; |
1338 | } | 1345 | } |
1339 | 1346 | ||
1347 | static int raw3270_pm_stop(struct ccw_device *cdev) | ||
1348 | { | ||
1349 | struct raw3270 *rp; | ||
1350 | struct raw3270_view *view; | ||
1351 | unsigned long flags; | ||
1352 | |||
1353 | rp = cdev->dev.driver_data; | ||
1354 | if (!rp) | ||
1355 | return 0; | ||
1356 | spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags); | ||
1357 | if (rp->view) | ||
1358 | rp->view->fn->deactivate(rp->view); | ||
1359 | if (!test_bit(RAW3270_FLAGS_CONSOLE, &rp->flags)) { | ||
1360 | /* | ||
1361 | * Release tty and fullscreen for all non-console | ||
1362 | * devices. | ||
1363 | */ | ||
1364 | list_for_each_entry(view, &rp->view_list, list) { | ||
1365 | if (view->fn->release) | ||
1366 | view->fn->release(view); | ||
1367 | } | ||
1368 | } | ||
1369 | set_bit(RAW3270_FLAGS_FROZEN, &rp->flags); | ||
1370 | spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags); | ||
1371 | return 0; | ||
1372 | } | ||
1373 | |||
1374 | static int raw3270_pm_start(struct ccw_device *cdev) | ||
1375 | { | ||
1376 | struct raw3270 *rp; | ||
1377 | unsigned long flags; | ||
1378 | |||
1379 | rp = cdev->dev.driver_data; | ||
1380 | if (!rp) | ||
1381 | return 0; | ||
1382 | spin_lock_irqsave(get_ccwdev_lock(rp->cdev), flags); | ||
1383 | clear_bit(RAW3270_FLAGS_FROZEN, &rp->flags); | ||
1384 | if (rp->view) | ||
1385 | rp->view->fn->activate(rp->view); | ||
1386 | spin_unlock_irqrestore(get_ccwdev_lock(rp->cdev), flags); | ||
1387 | return 0; | ||
1388 | } | ||
1389 | |||
1390 | void raw3270_pm_unfreeze(struct raw3270_view *view) | ||
1391 | { | ||
1392 | struct raw3270 *rp; | ||
1393 | |||
1394 | rp = view->dev; | ||
1395 | if (rp && test_bit(RAW3270_FLAGS_FROZEN, &rp->flags)) | ||
1396 | ccw_device_force_console(); | ||
1397 | } | ||
1398 | |||
1340 | static struct ccw_device_id raw3270_id[] = { | 1399 | static struct ccw_device_id raw3270_id[] = { |
1341 | { CCW_DEVICE(0x3270, 0) }, | 1400 | { CCW_DEVICE(0x3270, 0) }, |
1342 | { CCW_DEVICE(0x3271, 0) }, | 1401 | { CCW_DEVICE(0x3271, 0) }, |
@@ -1360,6 +1419,9 @@ static struct ccw_driver raw3270_ccw_driver = { | |||
1360 | .remove = &raw3270_remove, | 1419 | .remove = &raw3270_remove, |
1361 | .set_online = &raw3270_set_online, | 1420 | .set_online = &raw3270_set_online, |
1362 | .set_offline = &raw3270_set_offline, | 1421 | .set_offline = &raw3270_set_offline, |
1422 | .freeze = &raw3270_pm_stop, | ||
1423 | .thaw = &raw3270_pm_start, | ||
1424 | .restore = &raw3270_pm_start, | ||
1363 | }; | 1425 | }; |
1364 | 1426 | ||
1365 | static int | 1427 | static int |