diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c index 88e96957cbb2..caccf5d496fd 100644 --- a/drivers/s390/char/con3270.c +++ b/drivers/s390/char/con3270.c @@ -89,8 +89,6 @@ struct tty3270 { struct tty3270_attribute attributes; struct tty3270_attribute saved_attributes; struct tty3270_line *screen; - unsigned int n_model, n_cols, n_rows; /* New model & size */ - struct work_struct resize_work; /* Input stuff. */ struct string *prompt; /* Output string for input area. */ @@ -126,8 +124,6 @@ struct tty3270 { #define TTY_UPDATE_ALL 16 /* Recreate screen. */ static void tty3270_update(struct timer_list *); -static void tty3270_resize_work(struct work_struct *work); - /* * Setup timeout for a device. On timeout trigger an update. */ @@ -745,8 +741,6 @@ static struct tty3270 *tty3270_alloc_view(void) (unsigned long) tp->read); tasklet_init(&tp->hanglet, tty3270_hangup_tasklet, (unsigned long) tp); - INIT_WORK(&tp->resize_work, tty3270_resize_work); - return tp; out_reset: @@ -827,26 +821,36 @@ static void tty3270_free_screen(struct tty3270_line *screen, unsigned int rows) /* * Resize tty3270 screen */ -static void tty3270_resize_work(struct work_struct *work) +static void tty3270_resize(struct raw3270_view *view, + int new_model, int new_rows, int new_cols, + int old_model, int old_rows, int old_cols) { - struct tty3270 *tp = container_of(work, struct tty3270, resize_work); + struct tty3270 *tp = container_of(view, struct tty3270, view); struct tty3270_line *screen, *oscreen; struct tty_struct *tty; - unsigned int orows; struct winsize ws; - screen = tty3270_alloc_screen(tp->n_rows, tp->n_cols); + if (old_model == new_model && + old_cols == new_cols && + old_rows == new_rows) { + spin_lock_irq(&tp->view.lock); + tp->update_flags = TTY_UPDATE_ALL; + tty3270_set_timer(tp, 1); + spin_unlock_irq(&tp->view.lock); + return; + } + screen = tty3270_alloc_screen(new_rows, new_cols); if (IS_ERR(screen)) return; /* Switch to new output size */ spin_lock_irq(&tp->view.lock); tty3270_blank_screen(tp); oscreen = tp->screen; - orows = tp->view.rows; - tp->view.model = tp->n_model; - tp->view.rows = tp->n_rows; - tp->view.cols = tp->n_cols; tp->screen = screen; + tp->view.rows = new_rows; + tp->view.cols = new_cols; + tp->view.model = new_model; + free_string(&tp->freemem, tp->prompt); free_string(&tp->freemem, tp->status); tty3270_create_prompt(tp); @@ -855,7 +859,7 @@ static void tty3270_resize_work(struct work_struct *work) tty3270_blank_line(tp); tp->update_flags = TTY_UPDATE_ALL; spin_unlock_irq(&tp->view.lock); - tty3270_free_screen(oscreen, orows); + tty3270_free_screen(oscreen, old_rows); tty3270_set_timer(tp, 1); /* Informat tty layer about new size */ tty = tty_port_tty_get(&tp->port); @@ -867,18 +871,6 @@ static void tty3270_resize_work(struct work_struct *work) tty_kref_put(tty); } -static void tty3270_resize(struct raw3270_view *view, int model, int rows, int cols) -{ - struct tty3270 *tp = container_of(view, struct tty3270, view); - - if (tp->n_model == model && tp->n_rows == rows && tp->n_cols == cols) - return; - tp->n_model = model; - tp->n_rows = rows; - tp->n_cols = cols; - schedule_work(&tp->resize_work); -} - /* * Unlink tty3270 data structure from tty. */ diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index 68a6c7390c4c..032244c1dd78 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c @@ -37,7 +37,8 @@ struct raw3270 { struct ccw_device *cdev; int minor; - short model, rows, cols; + int model, rows, cols; + int old_model, old_rows, old_cols; unsigned int state; unsigned long flags; @@ -54,6 +55,7 @@ struct raw3270 { struct raw3270_request init_readpart; struct raw3270_request init_readmod; unsigned char init_data[256]; + struct work_struct resize_work; }; /* raw3270->state */ @@ -502,16 +504,20 @@ static void raw3270_size_device(struct raw3270 *rp) rp->model = 5; } -static void raw3270_size_device_done(struct raw3270 *rp) +static void raw3270_resize_work(struct work_struct *work) { + struct raw3270 *rp = container_of(work, struct raw3270, resize_work); struct raw3270_view *view; - rp->view = NULL; - rp->state = RAW3270_STATE_READY; /* Notify views about new size */ - list_for_each_entry(view, &rp->view_list, list) + list_for_each_entry(view, &rp->view_list, list) { if (view->fn->resize) - view->fn->resize(view, rp->model, rp->rows, rp->cols); + view->fn->resize(view, rp->model, rp->rows, rp->cols, + rp->old_model, rp->old_rows, rp->old_cols); + } + rp->old_cols = rp->cols; + rp->old_rows = rp->rows; + rp->old_model = rp->model; /* Setup processing done, now activate a view */ list_for_each_entry(view, &rp->view_list, list) { rp->view = view; @@ -521,6 +527,13 @@ static void raw3270_size_device_done(struct raw3270 *rp) } } +static void raw3270_size_device_done(struct raw3270 *rp) +{ + rp->view = NULL; + rp->state = RAW3270_STATE_READY; + schedule_work(&rp->resize_work); +} + static void raw3270_read_modified_cb(struct raw3270_request *rq, void *data) { struct raw3270 *rp = rq->view->dev; @@ -697,6 +710,8 @@ static int raw3270_setup_device(struct ccw_device *cdev, struct raw3270 *rp, /* Set defaults. */ rp->rows = 24; rp->cols = 80; + rp->old_rows = rp->rows; + rp->old_cols = rp->cols; INIT_LIST_HEAD(&rp->req_queue); INIT_LIST_HEAD(&rp->view_list); @@ -704,6 +719,7 @@ static int raw3270_setup_device(struct ccw_device *cdev, struct raw3270 *rp, rp->init_view.dev = rp; rp->init_view.fn = &raw3270_init_fn; rp->view = &rp->init_view; + INIT_WORK(&rp->resize_work, raw3270_resize_work); /* * Add device to list and find the smallest unused minor diff --git a/drivers/s390/char/raw3270.h b/drivers/s390/char/raw3270.h index c8e7a596051f..66f9f8d0e121 100644 --- a/drivers/s390/char/raw3270.h +++ b/drivers/s390/char/raw3270.h @@ -144,7 +144,7 @@ struct raw3270_fn { struct raw3270_request *, struct irb *); void (*release)(struct raw3270_view *); void (*free)(struct raw3270_view *); - void (*resize)(struct raw3270_view *, int, int, int); + void (*resize)(struct raw3270_view *, int, int, int, int, int, int); }; /*