aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
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
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')
-rw-r--r--drivers/s390/char/con3270.c38
-rw-r--r--drivers/s390/char/tty3270.c42
2 files changed, 32 insertions, 48 deletions
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c
index d028d2ee83dd..ed5396dae58e 100644
--- a/drivers/s390/char/con3270.c
+++ b/drivers/s390/char/con3270.c
@@ -64,7 +64,7 @@ static struct con3270 *condev;
64#define CON_UPDATE_ERASE 1 /* Use EWRITEA instead of WRITE. */ 64#define CON_UPDATE_ERASE 1 /* Use EWRITEA instead of WRITE. */
65#define CON_UPDATE_LIST 2 /* Update lines in tty3270->update. */ 65#define CON_UPDATE_LIST 2 /* Update lines in tty3270->update. */
66#define CON_UPDATE_STATUS 4 /* Update status line. */ 66#define CON_UPDATE_STATUS 4 /* Update status line. */
67#define CON_UPDATE_ALL 7 67#define CON_UPDATE_ALL 8 /* Recreate screen. */
68 68
69static void con3270_update(struct con3270 *); 69static void con3270_update(struct con3270 *);
70 70
@@ -73,18 +73,10 @@ static void con3270_update(struct con3270 *);
73 */ 73 */
74static void con3270_set_timer(struct con3270 *cp, int expires) 74static void con3270_set_timer(struct con3270 *cp, int expires)
75{ 75{
76 if (expires == 0) { 76 if (expires == 0)
77 if (timer_pending(&cp->timer)) 77 del_timer(&cp->timer);
78 del_timer(&cp->timer); 78 else
79 return; 79 mod_timer(&cp->timer, jiffies + expires);
80 }
81 if (timer_pending(&cp->timer) &&
82 mod_timer(&cp->timer, jiffies + expires))
83 return;
84 cp->timer.function = (void (*)(unsigned long)) con3270_update;
85 cp->timer.data = (unsigned long) cp;
86 cp->timer.expires = jiffies + expires;
87 add_timer(&cp->timer);
88} 80}
89 81
90/* 82/*
@@ -225,6 +217,12 @@ con3270_update(struct con3270 *cp)
225 217
226 spin_lock_irqsave(&cp->view.lock, flags); 218 spin_lock_irqsave(&cp->view.lock, flags);
227 updated = 0; 219 updated = 0;
220 if (cp->update_flags & CON_UPDATE_ALL) {
221 con3270_rebuild_update(cp);
222 con3270_update_status(cp);
223 cp->update_flags = CON_UPDATE_ERASE | CON_UPDATE_LIST |
224 CON_UPDATE_STATUS;
225 }
228 if (cp->update_flags & CON_UPDATE_ERASE) { 226 if (cp->update_flags & CON_UPDATE_ERASE) {
229 /* Use erase write alternate to initialize display. */ 227 /* Use erase write alternate to initialize display. */
230 raw3270_request_set_cmd(wrq, TC_EWRITEA); 228 raw3270_request_set_cmd(wrq, TC_EWRITEA);
@@ -302,7 +300,6 @@ con3270_read_tasklet(struct raw3270_request *rrq)
302 deactivate = 1; 300 deactivate = 1;
303 break; 301 break;
304 case 0x6d: /* clear: start from scratch. */ 302 case 0x6d: /* clear: start from scratch. */
305 con3270_rebuild_update(cp);
306 cp->update_flags = CON_UPDATE_ALL; 303 cp->update_flags = CON_UPDATE_ALL;
307 con3270_set_timer(cp, 1); 304 con3270_set_timer(cp, 1);
308 break; 305 break;
@@ -382,30 +379,21 @@ con3270_issue_read(struct con3270 *cp)
382static int 379static int
383con3270_activate(struct raw3270_view *view) 380con3270_activate(struct raw3270_view *view)
384{ 381{
385 unsigned long flags;
386 struct con3270 *cp; 382 struct con3270 *cp;
387 383
388 cp = (struct con3270 *) view; 384 cp = (struct con3270 *) view;
389 spin_lock_irqsave(&cp->view.lock, flags);
390 cp->nr_up = 0;
391 con3270_rebuild_update(cp);
392 con3270_update_status(cp);
393 cp->update_flags = CON_UPDATE_ALL; 385 cp->update_flags = CON_UPDATE_ALL;
394 con3270_set_timer(cp, 1); 386 con3270_set_timer(cp, 1);
395 spin_unlock_irqrestore(&cp->view.lock, flags);
396 return 0; 387 return 0;
397} 388}
398 389
399static void 390static void
400con3270_deactivate(struct raw3270_view *view) 391con3270_deactivate(struct raw3270_view *view)
401{ 392{
402 unsigned long flags;
403 struct con3270 *cp; 393 struct con3270 *cp;
404 394
405 cp = (struct con3270 *) view; 395 cp = (struct con3270 *) view;
406 spin_lock_irqsave(&cp->view.lock, flags);
407 del_timer(&cp->timer); 396 del_timer(&cp->timer);
408 spin_unlock_irqrestore(&cp->view.lock, flags);
409} 397}
410 398
411static int 399static int
@@ -504,6 +492,7 @@ con3270_write(struct console *co, const char *str, unsigned int count)
504 con3270_cline_end(cp); 492 con3270_cline_end(cp);
505 } 493 }
506 /* Setup timer to output current console buffer after 1/10 second */ 494 /* Setup timer to output current console buffer after 1/10 second */
495 cp->nr_up = 0;
507 if (cp->view.dev && !timer_pending(&cp->timer)) 496 if (cp->view.dev && !timer_pending(&cp->timer))
508 con3270_set_timer(cp, HZ/10); 497 con3270_set_timer(cp, HZ/10);
509 spin_unlock_irqrestore(&cp->view.lock,flags); 498 spin_unlock_irqrestore(&cp->view.lock,flags);
@@ -624,7 +613,8 @@ con3270_init(void)
624 613
625 INIT_LIST_HEAD(&condev->lines); 614 INIT_LIST_HEAD(&condev->lines);
626 INIT_LIST_HEAD(&condev->update); 615 INIT_LIST_HEAD(&condev->update);
627 init_timer(&condev->timer); 616 setup_timer(&condev->timer, (void (*)(unsigned long)) con3270_update,
617 (unsigned long) condev);
628 tasklet_init(&condev->readlet, 618 tasklet_init(&condev->readlet,
629 (void (*)(unsigned long)) con3270_read_tasklet, 619 (void (*)(unsigned long)) con3270_read_tasklet,
630 (unsigned long) condev->read); 620 (unsigned long) condev->read);
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);