From fe2fc9ca5d7e5d9144a4039d89a6f1f8967d9263 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 2 Apr 2012 13:54:08 +0200 Subject: TTY: con3215, centralize allocation There are two copies of allocations of device information. One of them is totally broken. See: raw->cdev = cdev; raw->inbuf = (char *) raw + sizeof(struct raw3215_info); memset(raw, 0, sizeof(struct raw3215_info)); It suggests that this path was never executed. The code uses both raw->cdev and raw->inbuf all over. And it is NULL due to the memset here, so it would panic immediately. I believe nobody used that driver without being a system console. Either way, let us fix it by moving the allocations (and initializations) to a single place. This will save us some double initializations later too. And while at it, initialize the timer properly -- once, at the allocation. Signed-off-by: Jiri Slaby Cc: Martin Schwidefsky Acked-by: Heiko Carstens Cc: linux390@de.ibm.com Cc: linux-s390@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/s390/char/con3215.c | 74 ++++++++++++++++++++++++--------------------- 1 file changed, 39 insertions(+), 35 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 4f9f1dcc1551..7e30f85ee3a5 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -324,10 +324,7 @@ static inline void raw3215_try_io(struct raw3215_info *raw) } } else if (!(raw->flags & RAW3215_TIMER_RUNS)) { /* delay small writes */ - init_timer(&raw->timer); raw->timer.expires = RAW3215_TIMEOUT + jiffies; - raw->timer.data = (unsigned long) raw; - raw->timer.function = raw3215_timeout; add_timer(&raw->timer); raw->flags |= RAW3215_TIMER_RUNS; } @@ -648,6 +645,35 @@ static void raw3215_shutdown(struct raw3215_info *raw) spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); } +static struct raw3215_info *raw3215_alloc_info(void) +{ + struct raw3215_info *info; + + info = kzalloc(sizeof(struct raw3215_info), GFP_KERNEL | GFP_DMA); + if (!info) + return NULL; + + info->buffer = kzalloc(RAW3215_BUFFER_SIZE, GFP_KERNEL | GFP_DMA); + info->inbuf = kzalloc(RAW3215_INBUF_SIZE, GFP_KERNEL | GFP_DMA); + if (!info->buffer || !info->inbuf) { + kfree(info); + return NULL; + } + + setup_timer(&info->timer, raw3215_timeout, (unsigned long)info); + init_waitqueue_head(&info->empty_wait); + tasklet_init(&info->tlet, raw3215_wakeup, (unsigned long)info); + + return info; +} + +static void raw3215_free_info(struct raw3215_info *raw) +{ + kfree(raw->inbuf); + kfree(raw->buffer); + kfree(raw); +} + static int raw3215_probe (struct ccw_device *cdev) { struct raw3215_info *raw; @@ -656,11 +682,15 @@ static int raw3215_probe (struct ccw_device *cdev) /* Console is special. */ if (raw3215[0] && (raw3215[0] == dev_get_drvdata(&cdev->dev))) return 0; - raw = kmalloc(sizeof(struct raw3215_info) + - RAW3215_INBUF_SIZE, GFP_KERNEL|GFP_DMA); + + raw = raw3215_alloc_info(); if (raw == NULL) return -ENOMEM; + raw->cdev = cdev; + dev_set_drvdata(&cdev->dev, raw); + cdev->handler = raw3215_irq; + spin_lock(&raw3215_device_lock); for (line = 0; line < NR_3215; line++) { if (!raw3215[line]) { @@ -670,28 +700,10 @@ static int raw3215_probe (struct ccw_device *cdev) } spin_unlock(&raw3215_device_lock); if (line == NR_3215) { - kfree(raw); + raw3215_free_info(raw); return -ENODEV; } - raw->cdev = cdev; - raw->inbuf = (char *) raw + sizeof(struct raw3215_info); - memset(raw, 0, sizeof(struct raw3215_info)); - raw->buffer = kmalloc(RAW3215_BUFFER_SIZE, - GFP_KERNEL|GFP_DMA); - if (raw->buffer == NULL) { - spin_lock(&raw3215_device_lock); - raw3215[line] = NULL; - spin_unlock(&raw3215_device_lock); - kfree(raw); - return -ENOMEM; - } - init_waitqueue_head(&raw->empty_wait); - tasklet_init(&raw->tlet, raw3215_wakeup, (unsigned long) raw); - - dev_set_drvdata(&cdev->dev, raw); - cdev->handler = raw3215_irq; - return 0; } @@ -703,8 +715,7 @@ static void raw3215_remove (struct ccw_device *cdev) raw = dev_get_drvdata(&cdev->dev); if (raw) { dev_set_drvdata(&cdev->dev, NULL); - kfree(raw->buffer); - kfree(raw); + raw3215_free_info(raw); } } @@ -897,23 +908,16 @@ static int __init con3215_init(void) if (IS_ERR(cdev)) return -ENODEV; - raw3215[0] = raw = (struct raw3215_info *) - kzalloc(sizeof(struct raw3215_info), GFP_KERNEL | GFP_DMA); - raw->buffer = kzalloc(RAW3215_BUFFER_SIZE, GFP_KERNEL | GFP_DMA); - raw->inbuf = kzalloc(RAW3215_INBUF_SIZE, GFP_KERNEL | GFP_DMA); + raw3215[0] = raw = raw3215_alloc_info(); raw->cdev = cdev; dev_set_drvdata(&cdev->dev, raw); cdev->handler = raw3215_irq; raw->flags |= RAW3215_FIXED; - init_waitqueue_head(&raw->empty_wait); - tasklet_init(&raw->tlet, raw3215_wakeup, (unsigned long) raw); /* Request the console irq */ if (raw3215_startup(raw) != 0) { - kfree(raw->inbuf); - kfree(raw->buffer); - kfree(raw); + raw3215_free_info(raw); raw3215[0] = NULL; return -ENODEV; } -- cgit v1.2.3 From 0ea63da2ffa54f6196405010379d56f0c8085b7e Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 2 Apr 2012 13:54:12 +0200 Subject: TTY: sclp_tty, add tty_port tty_port will hold tty buffers in the future. So we need to have it even here. The only needed member here is tty, so let us store it in the structure now. Signed-off-by: Jiri Slaby Cc: Martin Schwidefsky Cc: Heiko Carstens Cc: linux390@de.ibm.com Cc: linux-s390@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/s390/char/sclp_tty.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c index 40a9d69c898e..e66a75b3822c 100644 --- a/drivers/s390/char/sclp_tty.c +++ b/drivers/s390/char/sclp_tty.c @@ -48,7 +48,7 @@ static struct sclp_buffer *sclp_ttybuf; /* Timer for delayed output of console messages. */ static struct timer_list sclp_tty_timer; -static struct tty_struct *sclp_tty; +static struct tty_port sclp_port; static unsigned char sclp_tty_chars[SCLP_TTY_BUF_SIZE]; static unsigned short int sclp_tty_chars_count; @@ -64,7 +64,7 @@ static int sclp_tty_columns = 80; static int sclp_tty_open(struct tty_struct *tty, struct file *filp) { - sclp_tty = tty; + tty_port_tty_set(&sclp_port, tty); tty->driver_data = NULL; tty->low_latency = 0; return 0; @@ -76,7 +76,7 @@ sclp_tty_close(struct tty_struct *tty, struct file *filp) { if (tty->count > 1) return; - sclp_tty = NULL; + tty_port_tty_set(&sclp_port, NULL); } /* @@ -108,6 +108,7 @@ sclp_tty_write_room (struct tty_struct *tty) static void sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc) { + struct tty_struct *tty; unsigned long flags; void *page; @@ -126,8 +127,10 @@ sclp_ttybuf_callback(struct sclp_buffer *buffer, int rc) spin_unlock_irqrestore(&sclp_tty_lock, flags); } while (buffer && sclp_emit_buffer(buffer, sclp_ttybuf_callback)); /* check if the tty needs a wake up call */ - if (sclp_tty != NULL) { - tty_wakeup(sclp_tty); + tty = tty_port_tty_get(&sclp_port); + if (tty != NULL) { + tty_wakeup(tty); + tty_kref_put(tty); } } @@ -326,21 +329,22 @@ sclp_tty_flush_buffer(struct tty_struct *tty) static void sclp_tty_input(unsigned char* buf, unsigned int count) { + struct tty_struct *tty = tty_port_tty_get(&sclp_port); unsigned int cchar; /* * If this tty driver is currently closed * then throw the received input away. */ - if (sclp_tty == NULL) + if (tty == NULL) return; - cchar = ctrlchar_handle(buf, count, sclp_tty); + cchar = ctrlchar_handle(buf, count, tty); switch (cchar & CTRLCHAR_MASK) { case CTRLCHAR_SYSRQ: break; case CTRLCHAR_CTRL: - tty_insert_flip_char(sclp_tty, cchar, TTY_NORMAL); - tty_flip_buffer_push(sclp_tty); + tty_insert_flip_char(tty, cchar, TTY_NORMAL); + tty_flip_buffer_push(tty); break; case CTRLCHAR_NONE: /* send (normal) input to line discipline */ @@ -348,13 +352,14 @@ sclp_tty_input(unsigned char* buf, unsigned int count) (strncmp((const char *) buf + count - 2, "^n", 2) && strncmp((const char *) buf + count - 2, "\252n", 2))) { /* add the auto \n */ - tty_insert_flip_string(sclp_tty, buf, count); - tty_insert_flip_char(sclp_tty, '\n', TTY_NORMAL); + tty_insert_flip_string(tty, buf, count); + tty_insert_flip_char(tty, '\n', TTY_NORMAL); } else - tty_insert_flip_string(sclp_tty, buf, count - 2); - tty_flip_buffer_push(sclp_tty); + tty_insert_flip_string(tty, buf, count - 2); + tty_flip_buffer_push(tty); break; } + tty_kref_put(tty); } /* @@ -543,7 +548,7 @@ sclp_tty_init(void) sclp_tty_tolower = 1; } sclp_tty_chars_count = 0; - sclp_tty = NULL; + tty_port_init(&sclp_port); rc = sclp_register(&sclp_input_event); if (rc) { -- cgit v1.2.3 From 092f73779906899c687c5db58d2603c9619c7763 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 2 Apr 2012 13:54:13 +0200 Subject: TTY: sclp_vt220, add tty_port tty_port will hold tty buffers in the future. So we need to have it even here. The only needed member here is tty, so let us store it in the structure now. Signed-off-by: Jiri Slaby Cc: Martin Schwidefsky Cc: Heiko Carstens Cc: linux390@de.ibm.com Cc: linux-s390@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/s390/char/sclp_vt220.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c index b635472ae660..25cf2e8c162a 100644 --- a/drivers/s390/char/sclp_vt220.c +++ b/drivers/s390/char/sclp_vt220.c @@ -56,8 +56,7 @@ struct sclp_vt220_sccb { /* Structures and data needed to register tty driver */ static struct tty_driver *sclp_vt220_driver; -/* The tty_struct that the kernel associated with us */ -static struct tty_struct *sclp_vt220_tty; +static struct tty_port sclp_vt220_port; /* Lock to protect internal data from concurrent access */ static spinlock_t sclp_vt220_lock; @@ -116,6 +115,7 @@ static struct sclp_register sclp_vt220_register = { static void sclp_vt220_process_queue(struct sclp_vt220_request *request) { + struct tty_struct *tty; unsigned long flags; void *page; @@ -141,8 +141,10 @@ sclp_vt220_process_queue(struct sclp_vt220_request *request) if (request == NULL && sclp_vt220_flush_later) sclp_vt220_emit_current(); /* Check if the tty needs a wake up call */ - if (sclp_vt220_tty != NULL) { - tty_wakeup(sclp_vt220_tty); + tty = tty_port_tty_get(&sclp_vt220_port); + if (tty) { + tty_wakeup(tty); + tty_kref_put(tty); } } @@ -460,11 +462,12 @@ sclp_vt220_write(struct tty_struct *tty, const unsigned char *buf, int count) static void sclp_vt220_receiver_fn(struct evbuf_header *evbuf) { + struct tty_struct *tty = tty_port_tty_get(&sclp_vt220_port); char *buffer; unsigned int count; /* Ignore input if device is not open */ - if (sclp_vt220_tty == NULL) + if (tty == NULL) return; buffer = (char *) ((addr_t) evbuf + sizeof(struct evbuf_header)); @@ -478,10 +481,11 @@ sclp_vt220_receiver_fn(struct evbuf_header *evbuf) /* Send input to line discipline */ buffer++; count--; - tty_insert_flip_string(sclp_vt220_tty, buffer, count); - tty_flip_buffer_push(sclp_vt220_tty); + tty_insert_flip_string(tty, buffer, count); + tty_flip_buffer_push(tty); break; } + tty_kref_put(tty); } /* @@ -491,7 +495,7 @@ static int sclp_vt220_open(struct tty_struct *tty, struct file *filp) { if (tty->count == 1) { - sclp_vt220_tty = tty; + tty_port_tty_set(&sclp_vt220_port, tty); tty->driver_data = kmalloc(SCLP_VT220_BUF_SIZE, GFP_KERNEL); if (tty->driver_data == NULL) return -ENOMEM; @@ -511,7 +515,7 @@ static void sclp_vt220_close(struct tty_struct *tty, struct file *filp) { if (tty->count == 1) { - sclp_vt220_tty = NULL; + tty_port_tty_set(&sclp_vt220_port, NULL); kfree(tty->driver_data); tty->driver_data = NULL; } @@ -635,9 +639,9 @@ static int __init __sclp_vt220_init(int num_pages) INIT_LIST_HEAD(&sclp_vt220_empty); INIT_LIST_HEAD(&sclp_vt220_outqueue); init_timer(&sclp_vt220_timer); + tty_port_init(&sclp_vt220_port); sclp_vt220_current_request = NULL; sclp_vt220_buffered_chars = 0; - sclp_vt220_tty = NULL; sclp_vt220_flush_later = 0; /* Allocate pages for output buffering */ -- cgit v1.2.3 From b538c4eaf29176da55804963fb6a77883be6400a Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 2 Apr 2012 13:54:14 +0200 Subject: TTY: sclp_vt220, remove unused allocation 80 bytes which are allocated in tty->ops->open and assigned to tty->driver_data are never used. Remove that. Signed-off-by: Jiri Slaby Cc: Martin Schwidefsky Cc: Heiko Carstens Cc: linux390@de.ibm.com Cc: linux-s390@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/s390/char/sclp_vt220.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c index 25cf2e8c162a..edfc0fd73dc6 100644 --- a/drivers/s390/char/sclp_vt220.c +++ b/drivers/s390/char/sclp_vt220.c @@ -34,7 +34,6 @@ #define SCLP_VT220_DEVICE_NAME "ttysclp" #define SCLP_VT220_CONSOLE_NAME "ttyS" #define SCLP_VT220_CONSOLE_INDEX 1 /* console=ttyS1 */ -#define SCLP_VT220_BUF_SIZE 80 /* Representation of a single write request */ struct sclp_vt220_request { @@ -496,9 +495,6 @@ sclp_vt220_open(struct tty_struct *tty, struct file *filp) { if (tty->count == 1) { tty_port_tty_set(&sclp_vt220_port, tty); - tty->driver_data = kmalloc(SCLP_VT220_BUF_SIZE, GFP_KERNEL); - if (tty->driver_data == NULL) - return -ENOMEM; tty->low_latency = 0; if (!tty->winsize.ws_row && !tty->winsize.ws_col) { tty->winsize.ws_row = 24; @@ -514,11 +510,8 @@ sclp_vt220_open(struct tty_struct *tty, struct file *filp) static void sclp_vt220_close(struct tty_struct *tty, struct file *filp) { - if (tty->count == 1) { + if (tty->count == 1) tty_port_tty_set(&sclp_vt220_port, NULL); - kfree(tty->driver_data); - tty->driver_data = NULL; - } } /* -- cgit v1.2.3 From 9d2ae2335ce69249403061da4f0da63d9b0763f6 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 2 Apr 2012 13:54:15 +0200 Subject: TTY: tty3270, move initialization to allocation Let us initialize all the tty3270's members at the place where the structure is allocated. It cleans up tty->ops->open a bit. Signed-off-by: Jiri Slaby Cc: Martin Schwidefsky Cc: Heiko Carstens Cc: linux390@de.ibm.com Cc: linux-s390@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/s390/char/tty3270.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c index b43445a55cb6..f3837da7ceab 100644 --- a/drivers/s390/char/tty3270.c +++ b/drivers/s390/char/tty3270.c @@ -690,6 +690,16 @@ tty3270_alloc_view(void) if (!tp->freemem_pages) goto out_tp; INIT_LIST_HEAD(&tp->freemem); + INIT_LIST_HEAD(&tp->lines); + INIT_LIST_HEAD(&tp->update); + INIT_LIST_HEAD(&tp->rcl_lines); + tp->rcl_max = 20; + setup_timer(&tp->timer, (void (*)(unsigned long)) tty3270_update, + (unsigned long) tp); + tasklet_init(&tp->readlet, + (void (*)(unsigned long)) tty3270_read_tasklet, + (unsigned long) tp->read); + for (pages = 0; pages < TTY3270_STRING_PAGES; pages++) { tp->freemem_pages[pages] = (void *) __get_free_pages(GFP_KERNEL|GFP_DMA, 0); @@ -879,16 +889,6 @@ tty3270_open(struct tty_struct *tty, struct file * filp) if (IS_ERR(tp)) return PTR_ERR(tp); - INIT_LIST_HEAD(&tp->lines); - INIT_LIST_HEAD(&tp->update); - INIT_LIST_HEAD(&tp->rcl_lines); - tp->rcl_max = 20; - setup_timer(&tp->timer, (void (*)(unsigned long)) tty3270_update, - (unsigned long) tp); - tasklet_init(&tp->readlet, - (void (*)(unsigned long)) tty3270_read_tasklet, - (unsigned long) tp->read); - rc = raw3270_add_view(&tp->view, &tty3270_fn, tty->index + RAW3270_FIRSTMINOR); if (rc) { -- cgit v1.2.3 From 881e18f960478013b49a48ed6f7b3bf60c6f874f Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 2 Apr 2012 13:54:16 +0200 Subject: TTY: tty3270, get rid of ugly aliasing Blah, do not assume that raw3270_view is at the beginning of tty3270. Use proper types and container_of wherever needed. Signed-off-by: Jiri Slaby Cc: Martin Schwidefsky Cc: Heiko Carstens Cc: linux390@de.ibm.com Cc: linux-s390@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/s390/char/tty3270.c | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c index f3837da7ceab..bb1514a27f50 100644 --- a/drivers/s390/char/tty3270.c +++ b/drivers/s390/char/tty3270.c @@ -324,9 +324,8 @@ tty3270_blank_line(struct tty3270 *tp) static void tty3270_write_callback(struct raw3270_request *rq, void *data) { - struct tty3270 *tp; + struct tty3270 *tp = container_of(rq->view, struct tty3270, view); - tp = (struct tty3270 *) rq->view; if (rq->rc != 0) { /* Write wasn't successful. Refresh all. */ tp->update_flags = TTY_UPDATE_ALL; @@ -537,11 +536,10 @@ static void tty3270_read_tasklet(struct raw3270_request *rrq) { static char kreset_data = TW_KR; - struct tty3270 *tp; + struct tty3270 *tp = container_of(rrq->view, struct tty3270, view); char *input; int len; - tp = (struct tty3270 *) rrq->view; spin_lock_bh(&tp->view.lock); /* * Two AID keys are special: For 0x7d (enter) the input line @@ -596,9 +594,10 @@ tty3270_read_tasklet(struct raw3270_request *rrq) static void tty3270_read_callback(struct raw3270_request *rq, void *data) { + struct tty3270 *tp = container_of(rq->view, struct tty3270, view); raw3270_get_view(rq->view); /* Schedule tasklet to pass input to tty. */ - tasklet_schedule(&((struct tty3270 *) rq->view)->readlet); + tasklet_schedule(&tp->readlet); } /* @@ -635,9 +634,8 @@ tty3270_issue_read(struct tty3270 *tp, int lock) static int tty3270_activate(struct raw3270_view *view) { - struct tty3270 *tp; + struct tty3270 *tp = container_of(view, struct tty3270, view); - tp = (struct tty3270 *) view; tp->update_flags = TTY_UPDATE_ALL; tty3270_set_timer(tp, 1); return 0; @@ -646,9 +644,8 @@ tty3270_activate(struct raw3270_view *view) static void tty3270_deactivate(struct raw3270_view *view) { - struct tty3270 *tp; + struct tty3270 *tp = container_of(view, struct tty3270, view); - tp = (struct tty3270 *) view; del_timer(&tp->timer); } @@ -804,10 +801,9 @@ tty3270_free_screen(struct tty3270 *tp) static void tty3270_release(struct raw3270_view *view) { - struct tty3270 *tp; + struct tty3270 *tp = container_of(view, struct tty3270, view); struct tty_struct *tty; - tp = (struct tty3270 *) view; tty = tp->tty; if (tty) { tty->driver_data = NULL; @@ -823,8 +819,9 @@ tty3270_release(struct raw3270_view *view) static void tty3270_free(struct raw3270_view *view) { - tty3270_free_screen((struct tty3270 *) view); - tty3270_free_view((struct tty3270 *) view); + struct tty3270 *tp = container_of(view, struct tty3270, view); + tty3270_free_screen(tp); + tty3270_free_view(tp); } /* @@ -833,14 +830,13 @@ tty3270_free(struct raw3270_view *view) static void tty3270_del_views(void) { - struct tty3270 *tp; int i; for (i = 0; i < tty3270_max_index; i++) { - tp = (struct tty3270 *) + struct raw3270_view *view = raw3270_find_view(&tty3270_fn, i + RAW3270_FIRSTMINOR); - if (!IS_ERR(tp)) - raw3270_del_view(&tp->view); + if (!IS_ERR(view)) + raw3270_del_view(view); } } @@ -858,16 +854,17 @@ static struct raw3270_fn tty3270_fn = { static int tty3270_open(struct tty_struct *tty, struct file * filp) { + struct raw3270_view *view; struct tty3270 *tp; int i, rc; if (tty->count > 1) return 0; /* Check if the tty3270 is already there. */ - tp = (struct tty3270 *) - raw3270_find_view(&tty3270_fn, + view = raw3270_find_view(&tty3270_fn, tty->index + RAW3270_FIRSTMINOR); - if (!IS_ERR(tp)) { + if (!IS_ERR(view)) { + tp = container_of(view, struct tty3270, view); tty->driver_data = tp; tty->winsize.ws_row = tp->view.rows - 2; tty->winsize.ws_col = tp->view.cols; @@ -881,7 +878,7 @@ tty3270_open(struct tty_struct *tty, struct file * filp) tty3270_max_index = tty->index + 1; /* Quick exit if there is no device for tty->index. */ - if (PTR_ERR(tp) == -ENODEV) + if (PTR_ERR(view) == -ENODEV) return -ENODEV; /* Allocate tty3270 structure on first open. */ @@ -935,11 +932,10 @@ tty3270_open(struct tty_struct *tty, struct file * filp) static void tty3270_close(struct tty_struct *tty, struct file * filp) { - struct tty3270 *tp; + struct tty3270 *tp = tty->driver_data; if (tty->count > 1) return; - tp = (struct tty3270 *) tty->driver_data; if (tp) { tty->driver_data = NULL; tp->tty = tp->kbd->tty = NULL; -- cgit v1.2.3 From 20acdfa85c1c0292ee710335900dc04aa7b634a3 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 2 Apr 2012 13:54:17 +0200 Subject: TTY: tty3270, push tty down to tty3270_do_write So that we do not need to access tp->tty there. It is going away. Signed-off-by: Jiri Slaby Cc: Martin Schwidefsky Cc: Heiko Carstens Cc: linux390@de.ibm.com Cc: linux-s390@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/s390/char/tty3270.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c index bb1514a27f50..1f4aff78eaca 100644 --- a/drivers/s390/char/tty3270.c +++ b/drivers/s390/char/tty3270.c @@ -1509,12 +1509,13 @@ tty3270_escape_sequence(struct tty3270 *tp, char ch) * String write routine for 3270 ttys */ static void -tty3270_do_write(struct tty3270 *tp, const unsigned char *buf, int count) +tty3270_do_write(struct tty3270 *tp, struct tty_struct *tty, + const unsigned char *buf, int count) { int i_msg, i; spin_lock_bh(&tp->view.lock); - for (i_msg = 0; !tp->tty->stopped && i_msg < count; i_msg++) { + for (i_msg = 0; !tty->stopped && i_msg < count; i_msg++) { if (tp->esc_state != 0) { /* Continue escape sequence. */ tty3270_escape_sequence(tp, buf[i_msg]); @@ -1591,10 +1592,10 @@ tty3270_write(struct tty_struct * tty, if (!tp) return 0; if (tp->char_count > 0) { - tty3270_do_write(tp, tp->char_buf, tp->char_count); + tty3270_do_write(tp, tty, tp->char_buf, tp->char_count); tp->char_count = 0; } - tty3270_do_write(tp, buf, count); + tty3270_do_write(tp, tty, buf, count); return count; } @@ -1625,7 +1626,7 @@ tty3270_flush_chars(struct tty_struct *tty) if (!tp) return; if (tp->char_count > 0) { - tty3270_do_write(tp, tp->char_buf, tp->char_count); + tty3270_do_write(tp, tty, tp->char_buf, tp->char_count); tp->char_count = 0; } } -- cgit v1.2.3 From ba186e7d17ea874f2a56385806e0ef213f58a1dd Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 2 Apr 2012 13:54:18 +0200 Subject: TTY: tty3270, add tty_port And use tty from that. This means, we convert most of the users to accept tty_port instead. This is not racy and ensures the tty to be properly refcounted. Signed-off-by: Jiri Slaby Cc: Martin Schwidefsky Cc: Heiko Carstens Cc: linux390@de.ibm.com Cc: linux-s390@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/s390/char/keyboard.c | 30 +++++++++++++++------------ drivers/s390/char/keyboard.h | 14 ++++++++++--- drivers/s390/char/tty3270.c | 48 +++++++++++++++++++------------------------- 3 files changed, 49 insertions(+), 43 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c index 806588192483..7ef9cfdc17d8 100644 --- a/drivers/s390/char/keyboard.c +++ b/drivers/s390/char/keyboard.c @@ -199,7 +199,7 @@ handle_diacr(struct kbd_data *kbd, unsigned int ch) if (ch == ' ' || ch == d) return d; - kbd_put_queue(kbd->tty, d); + kbd_put_queue(kbd->port, d); return ch; } @@ -221,7 +221,7 @@ k_self(struct kbd_data *kbd, unsigned char value) { if (kbd->diacr) value = handle_diacr(kbd, value); - kbd_put_queue(kbd->tty, value); + kbd_put_queue(kbd->port, value); } /* @@ -239,7 +239,7 @@ static void k_fn(struct kbd_data *kbd, unsigned char value) { if (kbd->func_table[value]) - kbd_puts_queue(kbd->tty, kbd->func_table[value]); + kbd_puts_queue(kbd->port, kbd->func_table[value]); } static void @@ -257,20 +257,20 @@ k_spec(struct kbd_data *kbd, unsigned char value) * but we need only 16 bits here */ static void -to_utf8(struct tty_struct *tty, ushort c) +to_utf8(struct tty_port *port, ushort c) { if (c < 0x80) /* 0******* */ - kbd_put_queue(tty, c); + kbd_put_queue(port, c); else if (c < 0x800) { /* 110***** 10****** */ - kbd_put_queue(tty, 0xc0 | (c >> 6)); - kbd_put_queue(tty, 0x80 | (c & 0x3f)); + kbd_put_queue(port, 0xc0 | (c >> 6)); + kbd_put_queue(port, 0x80 | (c & 0x3f)); } else { /* 1110**** 10****** 10****** */ - kbd_put_queue(tty, 0xe0 | (c >> 12)); - kbd_put_queue(tty, 0x80 | ((c >> 6) & 0x3f)); - kbd_put_queue(tty, 0x80 | (c & 0x3f)); + kbd_put_queue(port, 0xe0 | (c >> 12)); + kbd_put_queue(port, 0x80 | ((c >> 6) & 0x3f)); + kbd_put_queue(port, 0x80 | (c & 0x3f)); } } @@ -283,7 +283,7 @@ kbd_keycode(struct kbd_data *kbd, unsigned int keycode) unsigned short keysym; unsigned char type, value; - if (!kbd || !kbd->tty) + if (!kbd) return; if (keycode >= 384) @@ -323,7 +323,7 @@ kbd_keycode(struct kbd_data *kbd, unsigned int keycode) #endif (*k_handler[type])(kbd, value); } else - to_utf8(kbd->tty, keysym); + to_utf8(kbd->port, keysym); } /* @@ -457,6 +457,7 @@ do_kdgkb_ioctl(struct kbd_data *kbd, struct kbsentry __user *u_kbs, int kbd_ioctl(struct kbd_data *kbd, unsigned int cmd, unsigned long arg) { + struct tty_struct *tty; void __user *argp; unsigned int ct; int perm; @@ -467,7 +468,10 @@ int kbd_ioctl(struct kbd_data *kbd, unsigned int cmd, unsigned long arg) * To have permissions to do most of the vt ioctls, we either have * to be the owner of the tty, or have CAP_SYS_TTY_CONFIG. */ - perm = current->signal->tty == kbd->tty || capable(CAP_SYS_TTY_CONFIG); + tty = tty_port_tty_get(kbd->port); + /* FIXME this test is pretty racy */ + perm = current->signal->tty == tty || capable(CAP_SYS_TTY_CONFIG); + tty_kref_put(tty); switch (cmd) { case KDGKBTYPE: return put_user(KB_101, (char __user *)argp); diff --git a/drivers/s390/char/keyboard.h b/drivers/s390/char/keyboard.h index 7e736aaeae6e..f682f4e49680 100644 --- a/drivers/s390/char/keyboard.h +++ b/drivers/s390/char/keyboard.h @@ -21,7 +21,7 @@ typedef void (fn_handler_fn)(struct kbd_data *); */ struct kbd_data { - struct tty_struct *tty; + struct tty_port *port; unsigned short **key_maps; char **func_table; fn_handler_fn **fn_handler; @@ -42,16 +42,24 @@ int kbd_ioctl(struct kbd_data *, unsigned int, unsigned long); * Helper Functions. */ static inline void -kbd_put_queue(struct tty_struct *tty, int ch) +kbd_put_queue(struct tty_port *port, int ch) { + struct tty_struct *tty = tty_port_tty_get(port); + if (!tty) + return; tty_insert_flip_char(tty, ch, 0); tty_schedule_flip(tty); + tty_kref_put(tty); } static inline void -kbd_puts_queue(struct tty_struct *tty, char *cp) +kbd_puts_queue(struct tty_port *port, char *cp) { + struct tty_struct *tty = tty_port_tty_get(port); + if (!tty) + return; while (*cp) tty_insert_flip_char(tty, *cp++, 0); tty_schedule_flip(tty); + tty_kref_put(tty); } diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c index 1f4aff78eaca..10ec690197cb 100644 --- a/drivers/s390/char/tty3270.c +++ b/drivers/s390/char/tty3270.c @@ -61,7 +61,7 @@ struct tty3270_line { */ struct tty3270 { struct raw3270_view view; - struct tty_struct *tty; /* Pointer to tty structure */ + struct tty_port port; void **freemem_pages; /* Array of pages used for freemem. */ struct list_head freemem; /* List of free memory for strings. */ @@ -449,10 +449,9 @@ tty3270_rcl_add(struct tty3270 *tp, char *input, int len) static void tty3270_rcl_backward(struct kbd_data *kbd) { - struct tty3270 *tp; + struct tty3270 *tp = container_of(kbd->port, struct tty3270, port); struct string *s; - tp = kbd->tty->driver_data; spin_lock_bh(&tp->view.lock); if (tp->inattr == TF_INPUT) { if (tp->rcl_walk && tp->rcl_walk->prev != &tp->rcl_lines) @@ -477,9 +476,8 @@ tty3270_rcl_backward(struct kbd_data *kbd) static void tty3270_exit_tty(struct kbd_data *kbd) { - struct tty3270 *tp; + struct tty3270 *tp = container_of(kbd->port, struct tty3270, port); - tp = kbd->tty->driver_data; raw3270_deactivate_view(&tp->view); } @@ -489,10 +487,9 @@ tty3270_exit_tty(struct kbd_data *kbd) static void tty3270_scroll_forward(struct kbd_data *kbd) { - struct tty3270 *tp; + struct tty3270 *tp = container_of(kbd->port, struct tty3270, port); int nr_up; - tp = kbd->tty->driver_data; spin_lock_bh(&tp->view.lock); nr_up = tp->nr_up - tp->view.rows + 2; if (nr_up < 0) @@ -512,10 +509,9 @@ tty3270_scroll_forward(struct kbd_data *kbd) static void tty3270_scroll_backward(struct kbd_data *kbd) { - struct tty3270 *tp; + struct tty3270 *tp = container_of(kbd->port, struct tty3270, port); int nr_up; - tp = kbd->tty->driver_data; spin_lock_bh(&tp->view.lock); nr_up = tp->nr_up + tp->view.rows - 2; if (nr_up + tp->view.rows - 2 > tp->nr_lines) @@ -575,13 +571,10 @@ tty3270_read_tasklet(struct raw3270_request *rrq) raw3270_request_add_data(tp->kreset, &kreset_data, 1); raw3270_start(&tp->view, tp->kreset); - /* Emit input string. */ - if (tp->tty) { - while (len-- > 0) - kbd_keycode(tp->kbd, *input++); - /* Emit keycode for AID byte. */ - kbd_keycode(tp->kbd, 256 + tp->input->string[0]); - } + while (len-- > 0) + kbd_keycode(tp->kbd, *input++); + /* Emit keycode for AID byte. */ + kbd_keycode(tp->kbd, 256 + tp->input->string[0]); raw3270_request_reset(rrq); xchg(&tp->read, rrq); @@ -691,6 +684,7 @@ tty3270_alloc_view(void) INIT_LIST_HEAD(&tp->update); INIT_LIST_HEAD(&tp->rcl_lines); tp->rcl_max = 20; + tty_port_init(&tp->port); setup_timer(&tp->timer, (void (*)(unsigned long)) tty3270_update, (unsigned long) tp); tasklet_init(&tp->readlet, @@ -802,14 +796,14 @@ static void tty3270_release(struct raw3270_view *view) { struct tty3270 *tp = container_of(view, struct tty3270, view); - struct tty_struct *tty; + struct tty_struct *tty = tty_port_tty_get(&tp->port); - tty = tp->tty; if (tty) { tty->driver_data = NULL; - tp->tty = tp->kbd->tty = NULL; + tty_port_tty_set(&tp->port, NULL); tty_hangup(tty); raw3270_put_view(&tp->view); + tty_kref_put(tty); } } @@ -869,8 +863,8 @@ tty3270_open(struct tty_struct *tty, struct file * filp) tty->winsize.ws_row = tp->view.rows - 2; tty->winsize.ws_col = tp->view.cols; tty->low_latency = 0; - tp->tty = tty; - tp->kbd->tty = tty; + /* why to reassign? */ + tty_port_tty_set(&tp->port, tty); tp->inattr = TF_INPUT; return 0; } @@ -900,7 +894,7 @@ tty3270_open(struct tty_struct *tty, struct file * filp) return rc; } - tp->tty = tty; + tty_port_tty_set(&tp->port, tty); tty->low_latency = 0; tty->driver_data = tp; tty->winsize.ws_row = tp->view.rows - 2; @@ -914,7 +908,7 @@ tty3270_open(struct tty_struct *tty, struct file * filp) for (i = 0; i < tp->view.rows - 2; i++) tty3270_blank_line(tp); - tp->kbd->tty = tty; + tp->kbd->port = &tp->port; tp->kbd->fn_handler[KVAL(K_INCRCONSOLE)] = tty3270_exit_tty; tp->kbd->fn_handler[KVAL(K_SCROLLBACK)] = tty3270_scroll_backward; tp->kbd->fn_handler[KVAL(K_SCROLLFORW)] = tty3270_scroll_forward; @@ -938,7 +932,7 @@ tty3270_close(struct tty_struct *tty, struct file * filp) return; if (tp) { tty->driver_data = NULL; - tp->tty = tp->kbd->tty = NULL; + tty_port_tty_set(&tp->port, NULL); raw3270_put_view(&tp->view); } } @@ -1387,7 +1381,7 @@ tty3270_escape_sequence(struct tty3270 *tp, char ch) tty3270_lf(tp); break; case 'Z': /* Respond ID. */ - kbd_puts_queue(tp->tty, "\033[?6c"); + kbd_puts_queue(&tp->port, "\033[?6c"); break; case '7': /* Save cursor position. */ tp->saved_cx = tp->cx; @@ -1433,11 +1427,11 @@ tty3270_escape_sequence(struct tty3270 *tp, char ch) tp->esc_state = ESnormal; if (ch == 'n' && !tp->esc_ques) { if (tp->esc_par[0] == 5) /* Status report. */ - kbd_puts_queue(tp->tty, "\033[0n"); + kbd_puts_queue(&tp->port, "\033[0n"); else if (tp->esc_par[0] == 6) { /* Cursor report. */ char buf[40]; sprintf(buf, "\033[%d;%dR", tp->cy + 1, tp->cx + 1); - kbd_puts_queue(tp->tty, buf); + kbd_puts_queue(&tp->port, buf); } return; } -- cgit v1.2.3 From 8dd360f042387aed5e2472d2246b677b7703274f Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 11 Apr 2012 11:14:58 +0200 Subject: TTY: con3215, add tty_port And use flags from that. But first we have to get rid of duplicated flag names. From now on, for the standard ones that are stored in tty_port->flags, we use ASYNC_* ones. Signed-off-by: Jiri Slaby Cc: Martin Schwidefsky Cc: Heiko Carstens Cc: linux390@de.ibm.com Cc: linux-s390@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/s390/char/con3215.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 7e30f85ee3a5..f7bc23baf540 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -20,6 +20,7 @@ #include #include #include +#include /* ASYNC_* flags */ #include #include #include @@ -44,14 +45,11 @@ #define RAW3215_TIMEOUT HZ/10 /* time for delayed output */ #define RAW3215_FIXED 1 /* 3215 console device is not be freed */ -#define RAW3215_ACTIVE 2 /* set if the device is in use */ #define RAW3215_WORKING 4 /* set if a request is being worked on */ #define RAW3215_THROTTLED 8 /* set if reading is disabled */ #define RAW3215_STOPPED 16 /* set if writing is disabled */ -#define RAW3215_CLOSING 32 /* set while in close process */ #define RAW3215_TIMER_RUNS 64 /* set if the output delay timer is on */ #define RAW3215_FLUSHING 128 /* set to flush buffer (no delay) */ -#define RAW3215_FROZEN 256 /* set if 3215 is frozen for suspend */ #define TAB_STOP_SIZE 8 /* tab stop size */ @@ -76,6 +74,7 @@ struct raw3215_req { } __attribute__ ((aligned(8))); struct raw3215_info { + struct tty_port port; struct ccw_device *cdev; /* device for tty driver */ spinlock_t *lock; /* pointer to irq lock */ int flags; /* state flags */ @@ -293,7 +292,7 @@ static void raw3215_timeout(unsigned long __data) if (raw->flags & RAW3215_TIMER_RUNS) { del_timer(&raw->timer); raw->flags &= ~RAW3215_TIMER_RUNS; - if (!(raw->flags & RAW3215_FROZEN)) { + if (!(raw->port.flags & ASYNC_SUSPENDED)) { raw3215_mk_write_req(raw); raw3215_start_io(raw); } @@ -309,7 +308,8 @@ static void raw3215_timeout(unsigned long __data) */ static inline void raw3215_try_io(struct raw3215_info *raw) { - if (!(raw->flags & RAW3215_ACTIVE) || (raw->flags & RAW3215_FROZEN)) + if (!(raw->port.flags & ASYNC_INITIALIZED) || + (raw->port.flags & ASYNC_SUSPENDED)) return; if (raw->queued_read != NULL) raw3215_start_io(raw); @@ -484,7 +484,7 @@ static void raw3215_make_room(struct raw3215_info *raw, unsigned int length) /* While console is frozen for suspend we have no other * choice but to drop message from the buffer to make * room for even more messages. */ - if (raw->flags & RAW3215_FROZEN) { + if (raw->port.flags & ASYNC_SUSPENDED) { raw3215_drop_line(raw); continue; } @@ -606,10 +606,10 @@ static int raw3215_startup(struct raw3215_info *raw) { unsigned long flags; - if (raw->flags & RAW3215_ACTIVE) + if (raw->port.flags & ASYNC_INITIALIZED) return 0; raw->line_pos = 0; - raw->flags |= RAW3215_ACTIVE; + raw->port.flags |= ASYNC_INITIALIZED; spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); raw3215_try_io(raw); spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); @@ -625,14 +625,15 @@ static void raw3215_shutdown(struct raw3215_info *raw) DECLARE_WAITQUEUE(wait, current); unsigned long flags; - if (!(raw->flags & RAW3215_ACTIVE) || (raw->flags & RAW3215_FIXED)) + if (!(raw->port.flags & ASYNC_INITIALIZED) || + (raw->flags & RAW3215_FIXED)) return; /* Wait for outstanding requests, then free irq */ spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); if ((raw->flags & RAW3215_WORKING) || raw->queued_write != NULL || raw->queued_read != NULL) { - raw->flags |= RAW3215_CLOSING; + raw->port.flags |= ASYNC_CLOSING; add_wait_queue(&raw->empty_wait, &wait); set_current_state(TASK_INTERRUPTIBLE); spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); @@ -640,7 +641,7 @@ static void raw3215_shutdown(struct raw3215_info *raw) spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); remove_wait_queue(&raw->empty_wait, &wait); set_current_state(TASK_RUNNING); - raw->flags &= ~(RAW3215_ACTIVE | RAW3215_CLOSING); + raw->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING); } spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); } @@ -663,6 +664,7 @@ static struct raw3215_info *raw3215_alloc_info(void) setup_timer(&info->timer, raw3215_timeout, (unsigned long)info); init_waitqueue_head(&info->empty_wait); tasklet_init(&info->tlet, raw3215_wakeup, (unsigned long)info); + tty_port_init(&info->port); return info; } @@ -752,7 +754,7 @@ static int raw3215_pm_stop(struct ccw_device *cdev) raw = dev_get_drvdata(&cdev->dev); spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); raw3215_make_room(raw, RAW3215_BUFFER_SIZE); - raw->flags |= RAW3215_FROZEN; + raw->port.flags |= ASYNC_SUSPENDED; spin_unlock_irqrestore(get_ccwdev_lock(raw->cdev), flags); return 0; } @@ -765,7 +767,7 @@ static int raw3215_pm_start(struct ccw_device *cdev) /* Allow I/O again and flush output buffer. */ raw = dev_get_drvdata(&cdev->dev); spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); - raw->flags &= ~RAW3215_FROZEN; + raw->port.flags &= ~ASYNC_SUSPENDED; raw->flags |= RAW3215_FLUSHING; raw3215_try_io(raw); raw->flags &= ~RAW3215_FLUSHING; @@ -838,7 +840,7 @@ static void con3215_flush(void) unsigned long flags; raw = raw3215[0]; /* console 3215 is the first one */ - if (raw->flags & RAW3215_FROZEN) + if (raw->port.flags & ASYNC_SUSPENDED) /* The console is still frozen for suspend. */ if (ccw_device_force_console()) /* Forcing didn't work, no panic message .. */ -- cgit v1.2.3 From 86b26007a37d81e7aca242bb5b649473f8f81297 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 11 Apr 2012 11:14:59 +0200 Subject: TTY: con3215, use tty from tty_port Obtain tty_struct only once in ISR and pass it down to raw3215_next_io. Other than that, we just use the tty with raised reference. And set it properly in open and close. Signed-off-by: Jiri Slaby Cc: Martin Schwidefsky Cc: Heiko Carstens Cc: linux390@de.ibm.com Cc: linux-s390@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/s390/char/con3215.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers/s390') diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index f7bc23baf540..e928e0408001 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -83,7 +83,6 @@ struct raw3215_info { int head; /* first free byte in output buffer */ int count; /* number of bytes in output buffer */ int written; /* number of bytes in write requests */ - struct tty_struct *tty; /* pointer to tty structure if present */ struct raw3215_req *queued_read; /* pointer to queued read requests */ struct raw3215_req *queued_write;/* pointer to queued write requests */ struct tasklet_struct tlet; /* tasklet to invoke tty_wakeup */ @@ -343,11 +342,11 @@ static void raw3215_wakeup(unsigned long data) /* * Try to start the next IO and wake up processes waiting on the tty. */ -static void raw3215_next_io(struct raw3215_info *raw) +static void raw3215_next_io(struct raw3215_info *raw, struct tty_struct *tty) { raw3215_mk_write_req(raw); raw3215_try_io(raw); - if (raw->tty && RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE) + if (tty && RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE) tasklet_schedule(&raw->tlet); } @@ -365,10 +364,11 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm, raw = dev_get_drvdata(&cdev->dev); req = (struct raw3215_req *) intparm; + tty = tty_port_tty_get(&raw->port); cstat = irb->scsw.cmd.cstat; dstat = irb->scsw.cmd.dstat; if (cstat != 0) - raw3215_next_io(raw); + raw3215_next_io(raw, tty); if (dstat & 0x01) { /* we got a unit exception */ dstat &= ~0x01; /* we can ignore it */ } @@ -378,13 +378,13 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm, break; /* Attention interrupt, someone hit the enter key */ raw3215_mk_read_req(raw); - raw3215_next_io(raw); + raw3215_next_io(raw, tty); break; case 0x08: case 0x0C: /* Channel end interrupt. */ if ((raw = req->info) == NULL) - return; /* That shouldn't happen ... */ + goto put_tty; /* That shouldn't happen ... */ if (req->type == RAW3215_READ) { /* store residual count, then wait for device end */ req->residual = irb->scsw.cmd.count; @@ -394,11 +394,10 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm, case 0x04: /* Device end interrupt. */ if ((raw = req->info) == NULL) - return; /* That shouldn't happen ... */ - if (req->type == RAW3215_READ && raw->tty != NULL) { + goto put_tty; /* That shouldn't happen ... */ + if (req->type == RAW3215_READ && tty != NULL) { unsigned int cchar; - tty = raw->tty; count = 160 - req->residual; EBCASC(raw->inbuf, count); cchar = ctrlchar_handle(raw->inbuf, count, tty); @@ -408,7 +407,7 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm, case CTRLCHAR_CTRL: tty_insert_flip_char(tty, cchar, TTY_NORMAL); - tty_flip_buffer_push(raw->tty); + tty_flip_buffer_push(tty); break; case CTRLCHAR_NONE: @@ -421,7 +420,7 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm, } else count -= 2; tty_insert_flip_string(tty, raw->inbuf, count); - tty_flip_buffer_push(raw->tty); + tty_flip_buffer_push(tty); break; } } else if (req->type == RAW3215_WRITE) { @@ -436,7 +435,7 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm, raw->queued_read == NULL) { wake_up_interruptible(&raw->empty_wait); } - raw3215_next_io(raw); + raw3215_next_io(raw, tty); break; default: /* Strange interrupt, I'll do my best to clean up */ @@ -448,9 +447,10 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm, raw->flags &= ~RAW3215_WORKING; raw3215_free_req(req); } - raw3215_next_io(raw); + raw3215_next_io(raw, tty); } - return; +put_tty: + tty_kref_put(tty); } /* @@ -946,7 +946,7 @@ static int tty3215_open(struct tty_struct *tty, struct file * filp) return -ENODEV; tty->driver_data = raw; - raw->tty = tty; + tty_port_tty_set(&raw->port, tty); tty->low_latency = 0; /* don't use bottom half for pushing chars */ /* @@ -977,7 +977,7 @@ static void tty3215_close(struct tty_struct *tty, struct file * filp) raw3215_shutdown(raw); tasklet_kill(&raw->tlet); tty->closing = 0; - raw->tty = NULL; + tty_port_tty_set(&raw->port, NULL); } /* -- cgit v1.2.3 From e695b28664827eaad4c8a4b6f921d3fae3e0f526 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 17 Apr 2012 13:16:34 +0200 Subject: tty: add missing tty_port_tty_get() call to raw3215_wakeup Fix compile error caused by "TTY: con3215, use tty from tty_port": CC drivers/s390/char/con3215.o drivers/s390/char/con3215.c: In function 'raw3215_wakeup': drivers/s390/char/con3215.c:339:16: error: 'struct raw3215_info' has no member named 'tty' make[1]: *** [drivers/s390/char/con3215.o] Error 1 make: *** [drivers/s390/char/] Error 2 Cc: Martin Schwidefsky Signed-off-by: Heiko Carstens Acked-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/s390/char/con3215.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/s390') diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index e928e0408001..6c0116d48c74 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c @@ -336,7 +336,11 @@ static inline void raw3215_try_io(struct raw3215_info *raw) static void raw3215_wakeup(unsigned long data) { struct raw3215_info *raw = (struct raw3215_info *) data; - tty_wakeup(raw->tty); + struct tty_struct *tty; + + tty = tty_port_tty_get(&raw->port); + tty_wakeup(tty); + tty_kref_put(tty); } /* -- cgit v1.2.3