aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/char/tty3270.c
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2009-06-12 04:26:31 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2009-06-12 04:27:33 -0400
commit205d7ab9c9af6847dda30650a0b8f98555a20654 (patch)
treeb77071becdd91a01ba2b30b3bdd79388f738b96b /drivers/s390/char/tty3270.c
parentfcf7581f7ca82e63e4e137be77c342a4e4ec8401 (diff)
[S390] 3270: lock dependency fixes
Lockdep found a problem with the lock order of the view lock and the ccw device lock. raw3270_activate_view/raw3270_deactivate_view first take the ccw device lock then call the activate/deactivate functions of the view which take view lock. The update functions of the con3270/tty3270 view will first take the view lock, then take the ccw device lock. To fix this the activate/deactivate functions are changed to avoid taking the view lock by moving the functions calls that modify the 3270 output buffer to the update function which is called by a timer. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/char/tty3270.c')
-rw-r--r--drivers/s390/char/tty3270.c42
1 files changed, 18 insertions, 24 deletions
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c
index aa7a114f6529..38385677c653 100644
--- a/drivers/s390/char/tty3270.c
+++ b/drivers/s390/char/tty3270.c
@@ -112,7 +112,7 @@ struct tty3270 {
112#define TTY_UPDATE_LIST 2 /* Update lines in tty3270->update. */ 112#define TTY_UPDATE_LIST 2 /* Update lines in tty3270->update. */
113#define TTY_UPDATE_INPUT 4 /* Update input line. */ 113#define TTY_UPDATE_INPUT 4 /* Update input line. */
114#define TTY_UPDATE_STATUS 8 /* Update status line. */ 114#define TTY_UPDATE_STATUS 8 /* Update status line. */
115#define TTY_UPDATE_ALL 15 115#define TTY_UPDATE_ALL 16 /* Recreate screen. */
116 116
117static void tty3270_update(struct tty3270 *); 117static void tty3270_update(struct tty3270 *);
118 118
@@ -121,19 +121,10 @@ static void tty3270_update(struct tty3270 *);
121 */ 121 */
122static void tty3270_set_timer(struct tty3270 *tp, int expires) 122static void tty3270_set_timer(struct tty3270 *tp, int expires)
123{ 123{
124 if (expires == 0) { 124 if (expires == 0)
125 if (timer_pending(&tp->timer) && del_timer(&tp->timer)) 125 del_timer(&tp->timer);
126 raw3270_put_view(&tp->view); 126 else
127 return; 127 mod_timer(&tp->timer, jiffies + expires);
128 }
129 if (timer_pending(&tp->timer) &&
130 mod_timer(&tp->timer, jiffies + expires))
131 return;
132 raw3270_get_view(&tp->view);
133 tp->timer.function = (void (*)(unsigned long)) tty3270_update;
134 tp->timer.data = (unsigned long) tp;
135 tp->timer.expires = jiffies + expires;
136 add_timer(&tp->timer);
137} 128}
138 129
139/* 130/*
@@ -337,7 +328,6 @@ tty3270_write_callback(struct raw3270_request *rq, void *data)
337 tp = (struct tty3270 *) rq->view; 328 tp = (struct tty3270 *) rq->view;
338 if (rq->rc != 0) { 329 if (rq->rc != 0) {
339 /* Write wasn't successfull. Refresh all. */ 330 /* Write wasn't successfull. Refresh all. */
340 tty3270_rebuild_update(tp);
341 tp->update_flags = TTY_UPDATE_ALL; 331 tp->update_flags = TTY_UPDATE_ALL;
342 tty3270_set_timer(tp, 1); 332 tty3270_set_timer(tp, 1);
343 } 333 }
@@ -366,6 +356,12 @@ tty3270_update(struct tty3270 *tp)
366 356
367 spin_lock(&tp->view.lock); 357 spin_lock(&tp->view.lock);
368 updated = 0; 358 updated = 0;
359 if (tp->update_flags & TTY_UPDATE_ALL) {
360 tty3270_rebuild_update(tp);
361 tty3270_update_status(tp);
362 tp->update_flags = TTY_UPDATE_ERASE | TTY_UPDATE_LIST |
363 TTY_UPDATE_INPUT | TTY_UPDATE_STATUS;
364 }
369 if (tp->update_flags & TTY_UPDATE_ERASE) { 365 if (tp->update_flags & TTY_UPDATE_ERASE) {
370 /* Use erase write alternate to erase display. */ 366 /* Use erase write alternate to erase display. */
371 raw3270_request_set_cmd(wrq, TC_EWRITEA); 367 raw3270_request_set_cmd(wrq, TC_EWRITEA);
@@ -425,7 +421,6 @@ tty3270_update(struct tty3270 *tp)
425 xchg(&tp->write, wrq); 421 xchg(&tp->write, wrq);
426 } 422 }
427 spin_unlock(&tp->view.lock); 423 spin_unlock(&tp->view.lock);
428 raw3270_put_view(&tp->view);
429} 424}
430 425
431/* 426/*
@@ -570,7 +565,6 @@ tty3270_read_tasklet(struct raw3270_request *rrq)
570 tty3270_set_timer(tp, 1); 565 tty3270_set_timer(tp, 1);
571 } else if (tp->input->string[0] == 0x6d) { 566 } else if (tp->input->string[0] == 0x6d) {
572 /* Display has been cleared. Redraw. */ 567 /* Display has been cleared. Redraw. */
573 tty3270_rebuild_update(tp);
574 tp->update_flags = TTY_UPDATE_ALL; 568 tp->update_flags = TTY_UPDATE_ALL;
575 tty3270_set_timer(tp, 1); 569 tty3270_set_timer(tp, 1);
576 } 570 }
@@ -641,22 +635,20 @@ static int
641tty3270_activate(struct raw3270_view *view) 635tty3270_activate(struct raw3270_view *view)
642{ 636{
643 struct tty3270 *tp; 637 struct tty3270 *tp;
644 unsigned long flags;
645 638
646 tp = (struct tty3270 *) view; 639 tp = (struct tty3270 *) view;
647 spin_lock_irqsave(&tp->view.lock, flags);
648 tp->nr_up = 0;
649 tty3270_rebuild_update(tp);
650 tty3270_update_status(tp);
651 tp->update_flags = TTY_UPDATE_ALL; 640 tp->update_flags = TTY_UPDATE_ALL;
652 tty3270_set_timer(tp, 1); 641 tty3270_set_timer(tp, 1);
653 spin_unlock_irqrestore(&tp->view.lock, flags);
654 return 0; 642 return 0;
655} 643}
656 644
657static void 645static void
658tty3270_deactivate(struct raw3270_view *view) 646tty3270_deactivate(struct raw3270_view *view)
659{ 647{
648 struct tty3270 *tp;
649
650 tp = (struct tty3270 *) view;
651 del_timer(&tp->timer);
660} 652}
661 653
662static int 654static int
@@ -743,6 +735,7 @@ tty3270_free_view(struct tty3270 *tp)
743{ 735{
744 int pages; 736 int pages;
745 737
738 del_timer_sync(&tp->timer);
746 kbd_free(tp->kbd); 739 kbd_free(tp->kbd);
747 raw3270_request_free(tp->kreset); 740 raw3270_request_free(tp->kreset);
748 raw3270_request_free(tp->read); 741 raw3270_request_free(tp->read);
@@ -889,7 +882,8 @@ tty3270_open(struct tty_struct *tty, struct file * filp)
889 INIT_LIST_HEAD(&tp->update); 882 INIT_LIST_HEAD(&tp->update);
890 INIT_LIST_HEAD(&tp->rcl_lines); 883 INIT_LIST_HEAD(&tp->rcl_lines);
891 tp->rcl_max = 20; 884 tp->rcl_max = 20;
892 init_timer(&tp->timer); 885 setup_timer(&tp->timer, (void (*)(unsigned long)) tty3270_update,
886 (unsigned long) tp);
893 tasklet_init(&tp->readlet, 887 tasklet_init(&tp->readlet,
894 (void (*)(unsigned long)) tty3270_read_tasklet, 888 (void (*)(unsigned long)) tty3270_read_tasklet,
895 (unsigned long) tp->read); 889 (unsigned long) tp->read);