diff options
Diffstat (limited to 'drivers/s390/char/sclp_tty.c')
| -rw-r--r-- | drivers/s390/char/sclp_tty.c | 87 |
1 files changed, 43 insertions, 44 deletions
diff --git a/drivers/s390/char/sclp_tty.c b/drivers/s390/char/sclp_tty.c index 236b736ae136..0a92d08830e7 100644 --- a/drivers/s390/char/sclp_tty.c +++ b/drivers/s390/char/sclp_tty.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * SCLP line mode terminal driver. * @@ -34,11 +35,11 @@ */ /* Lock to guard over changes to global variables. */ -static spinlock_t sclp_tty_lock; +static DEFINE_SPINLOCK(sclp_tty_lock); /* List of free pages that can be used for console output buffering. */ -static struct list_head sclp_tty_pages; +static LIST_HEAD(sclp_tty_pages); /* List of full struct sclp_buffer structures ready for output. */ -static struct list_head sclp_tty_outqueue; +static LIST_HEAD(sclp_tty_outqueue); /* Counter how many buffers are emitted. */ static int sclp_tty_buffer_count; /* Pointer to current console buffer. */ @@ -47,14 +48,14 @@ static struct sclp_buffer *sclp_ttybuf; static struct timer_list sclp_tty_timer; static struct tty_port sclp_port; -static unsigned char sclp_tty_chars[SCLP_TTY_BUF_SIZE]; +static u8 sclp_tty_chars[SCLP_TTY_BUF_SIZE]; static unsigned short int sclp_tty_chars_count; struct tty_driver *sclp_tty_driver; static int sclp_tty_tolower; -static int sclp_tty_columns = 80; +#define SCLP_TTY_COLUMNS 320 #define SPACES_PER_TAB 8 #define CASE_DELIMITER 0x6c /* to separate upper and lower case (% in EBCDIC) */ @@ -64,7 +65,6 @@ sclp_tty_open(struct tty_struct *tty, struct file *filp) { tty_port_tty_set(&sclp_port, tty); tty->driver_data = NULL; - sclp_port.low_latency = 0; return 0; } @@ -86,12 +86,12 @@ sclp_tty_close(struct tty_struct *tty, struct file *filp) * a string of newlines. Every newline creates a new message which * needs 82 bytes. */ -static int +static unsigned int sclp_tty_write_room (struct tty_struct *tty) { unsigned long flags; struct list_head *l; - int count; + unsigned int count; spin_lock_irqsave(&sclp_tty_lock, flags); count = 0; @@ -150,7 +150,7 @@ __sclp_ttybuf_emit(struct sclp_buffer *buffer) * temporary write buffer. */ static void -sclp_tty_timeout(unsigned long data) +sclp_tty_timeout(struct timer_list *unused) { unsigned long flags; struct sclp_buffer *buf; @@ -168,7 +168,7 @@ sclp_tty_timeout(unsigned long data) /* * Write a string to the sclp tty. */ -static int sclp_tty_write_string(const unsigned char *str, int count, int may_fail) +static int sclp_tty_write_string(const u8 *str, int count, int may_fail) { unsigned long flags; void *page; @@ -193,7 +193,7 @@ static int sclp_tty_write_string(const unsigned char *str, int count, int may_fa } page = sclp_tty_pages.next; list_del((struct list_head *) page); - sclp_ttybuf = sclp_make_buffer(page, sclp_tty_columns, + sclp_ttybuf = sclp_make_buffer(page, SCLP_TTY_COLUMNS, SPACES_PER_TAB); } /* try to write the string to the current output buffer */ @@ -217,11 +217,7 @@ static int sclp_tty_write_string(const unsigned char *str, int count, int may_fa /* Setup timer to output current console buffer after 1/10 second */ if (sclp_ttybuf && sclp_chars_in_buffer(sclp_ttybuf) && !timer_pending(&sclp_tty_timer)) { - init_timer(&sclp_tty_timer); - sclp_tty_timer.function = sclp_tty_timeout; - sclp_tty_timer.data = 0UL; - sclp_tty_timer.expires = jiffies + HZ/10; - add_timer(&sclp_tty_timer); + mod_timer(&sclp_tty_timer, jiffies + HZ / 10); } spin_unlock_irqrestore(&sclp_tty_lock, flags); out: @@ -233,8 +229,8 @@ out: * tty device. The characters may come from user space or kernel space. This * routine will return the number of characters actually accepted for writing. */ -static int -sclp_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) +static ssize_t +sclp_tty_write(struct tty_struct *tty, const u8 *buf, size_t count) { if (sclp_tty_chars_count > 0) { sclp_tty_write_string(sclp_tty_chars, sclp_tty_chars_count, 0); @@ -254,7 +250,7 @@ sclp_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) * sclp_write() without final '\n' - will be written. */ static int -sclp_tty_put_char(struct tty_struct *tty, unsigned char ch) +sclp_tty_put_char(struct tty_struct *tty, u8 ch) { sclp_tty_chars[sclp_tty_chars_count++] = ch; if (ch == '\n' || sclp_tty_chars_count >= SCLP_TTY_BUF_SIZE) { @@ -284,20 +280,17 @@ sclp_tty_flush_chars(struct tty_struct *tty) * characters in the write buffer (will not be written as long as there is a * final line feed missing). */ -static int +static unsigned int sclp_tty_chars_in_buffer(struct tty_struct *tty) { unsigned long flags; - struct list_head *l; struct sclp_buffer *t; - int count; + unsigned int count = 0; spin_lock_irqsave(&sclp_tty_lock, flags); - count = 0; if (sclp_ttybuf != NULL) count = sclp_chars_in_buffer(sclp_ttybuf); - list_for_each(l, &sclp_tty_outqueue) { - t = list_entry(l, struct sclp_buffer, list); + list_for_each_entry(t, &sclp_tty_outqueue, list) { count += sclp_chars_in_buffer(t); } spin_unlock_irqrestore(&sclp_tty_lock, flags); @@ -497,6 +490,17 @@ static const struct tty_operations sclp_ops = { .flush_buffer = sclp_tty_flush_buffer, }; +/* Release allocated pages. */ +static void __init __sclp_tty_free_pages(void) +{ + struct list_head *page, *p; + + list_for_each_safe(page, p, &sclp_tty_pages) { + list_del(page); + free_page((unsigned long)page); + } +} + static int __init sclp_tty_init(void) { @@ -505,38 +509,34 @@ sclp_tty_init(void) int i; int rc; - if (!CONSOLE_IS_SCLP) + /* z/VM multiplexes the line mode output on the 32xx screen */ + if (machine_is_vm() && !CONSOLE_IS_SCLP) return 0; - driver = alloc_tty_driver(1); - if (!driver) - return -ENOMEM; + if (!sclp.has_linemode) + return 0; + driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW); + if (IS_ERR(driver)) + return PTR_ERR(driver); rc = sclp_rw_init(); if (rc) { - put_tty_driver(driver); + tty_driver_kref_put(driver); return rc; } /* Allocate pages for output buffering */ - INIT_LIST_HEAD(&sclp_tty_pages); for (i = 0; i < MAX_KMEM_PAGES; i++) { page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA); if (page == NULL) { - put_tty_driver(driver); + __sclp_tty_free_pages(); + tty_driver_kref_put(driver); return -ENOMEM; } list_add_tail((struct list_head *) page, &sclp_tty_pages); } - INIT_LIST_HEAD(&sclp_tty_outqueue); - spin_lock_init(&sclp_tty_lock); - init_timer(&sclp_tty_timer); + timer_setup(&sclp_tty_timer, sclp_tty_timeout, 0); sclp_ttybuf = NULL; sclp_tty_buffer_count = 0; - if (MACHINE_IS_VM) { - /* - * save 4 characters for the CPU number - * written at start of each line by VM/CP - */ - sclp_tty_columns = 76; + if (machine_is_vm()) { /* case input lines to lowercase */ sclp_tty_tolower = 1; } @@ -544,7 +544,7 @@ sclp_tty_init(void) rc = sclp_register(&sclp_input_event); if (rc) { - put_tty_driver(driver); + tty_driver_kref_put(driver); return rc; } @@ -560,12 +560,11 @@ sclp_tty_init(void) driver->init_termios.c_iflag = IGNBRK | IGNPAR; driver->init_termios.c_oflag = ONLCR; driver->init_termios.c_lflag = ISIG | ECHO; - driver->flags = TTY_DRIVER_REAL_RAW; tty_set_operations(driver, &sclp_ops); tty_port_link_device(&sclp_port, driver, 0); rc = tty_register_driver(driver); if (rc) { - put_tty_driver(driver); + tty_driver_kref_put(driver); tty_port_destroy(&sclp_port); return rc; } |
