aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/char/raw3270.c
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2009-06-16 04:30:47 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2009-06-16 04:31:20 -0400
commit4b214a0c7720bfcfaca936047a359f8859fc8424 (patch)
tree33cbc967ffd4b7a316cada0917006bd7031ccfb2 /drivers/s390/char/raw3270.c
parent6a1d96dced593bc17d7a17fdb93c99b275e71eba (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.c84
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). */
66static DEFINE_MUTEX(raw3270_mutex); 66static 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
1347static 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
1374static 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
1390void 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
1340static struct ccw_device_id raw3270_id[] = { 1399static 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
1365static int 1427static int