diff options
author | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2009-06-12 04:26:31 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2009-06-12 04:27:33 -0400 |
commit | 205d7ab9c9af6847dda30650a0b8f98555a20654 (patch) | |
tree | b77071becdd91a01ba2b30b3bdd79388f738b96b /drivers/s390/char/tty3270.c | |
parent | fcf7581f7ca82e63e4e137be77c342a4e4ec8401 (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.c | 42 |
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 | ||
117 | static void tty3270_update(struct tty3270 *); | 117 | static void tty3270_update(struct tty3270 *); |
118 | 118 | ||
@@ -121,19 +121,10 @@ static void tty3270_update(struct tty3270 *); | |||
121 | */ | 121 | */ |
122 | static void tty3270_set_timer(struct tty3270 *tp, int expires) | 122 | static 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 | |||
641 | tty3270_activate(struct raw3270_view *view) | 635 | tty3270_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 | ||
657 | static void | 645 | static void |
658 | tty3270_deactivate(struct raw3270_view *view) | 646 | tty3270_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 | ||
662 | static int | 654 | static 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); |