cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

sclp_vt220.c (22422B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * SCLP VT220 terminal driver.
      4 *
      5 * Copyright IBM Corp. 2003, 2009
      6 *
      7 * Author(s): Peter Oberparleiter <Peter.Oberparleiter@de.ibm.com>
      8 */
      9
     10#include <linux/module.h>
     11#include <linux/spinlock.h>
     12#include <linux/panic_notifier.h>
     13#include <linux/list.h>
     14#include <linux/wait.h>
     15#include <linux/timer.h>
     16#include <linux/kernel.h>
     17#include <linux/sysrq.h>
     18#include <linux/tty.h>
     19#include <linux/tty_driver.h>
     20#include <linux/tty_flip.h>
     21#include <linux/errno.h>
     22#include <linux/mm.h>
     23#include <linux/major.h>
     24#include <linux/console.h>
     25#include <linux/kdev_t.h>
     26#include <linux/interrupt.h>
     27#include <linux/init.h>
     28#include <linux/reboot.h>
     29#include <linux/slab.h>
     30
     31#include <linux/uaccess.h>
     32#include "sclp.h"
     33#include "ctrlchar.h"
     34
     35#define SCLP_VT220_MAJOR		TTY_MAJOR
     36#define SCLP_VT220_MINOR		65
     37#define SCLP_VT220_DRIVER_NAME		"sclp_vt220"
     38#define SCLP_VT220_DEVICE_NAME		"ttysclp"
     39#define SCLP_VT220_CONSOLE_NAME		"ttysclp"
     40#define SCLP_VT220_CONSOLE_INDEX	0	/* console=ttysclp0 */
     41
     42/* Representation of a single write request */
     43struct sclp_vt220_request {
     44	struct list_head list;
     45	struct sclp_req sclp_req;
     46	int retry_count;
     47};
     48
     49/* VT220 SCCB */
     50struct sclp_vt220_sccb {
     51	struct sccb_header header;
     52	struct evbuf_header evbuf;
     53};
     54
     55#define SCLP_VT220_MAX_CHARS_PER_BUFFER	(PAGE_SIZE - \
     56					 sizeof(struct sclp_vt220_request) - \
     57					 sizeof(struct sclp_vt220_sccb))
     58
     59/* Structures and data needed to register tty driver */
     60static struct tty_driver *sclp_vt220_driver;
     61
     62static struct tty_port sclp_vt220_port;
     63
     64/* Lock to protect internal data from concurrent access */
     65static DEFINE_SPINLOCK(sclp_vt220_lock);
     66
     67/* List of empty pages to be used as write request buffers */
     68static LIST_HEAD(sclp_vt220_empty);
     69
     70/* List of pending requests */
     71static LIST_HEAD(sclp_vt220_outqueue);
     72
     73/* Flag that output queue is currently running */
     74static int sclp_vt220_queue_running;
     75
     76/* Timer used for delaying write requests to merge subsequent messages into
     77 * a single buffer */
     78static struct timer_list sclp_vt220_timer;
     79
     80/* Pointer to current request buffer which has been partially filled but not
     81 * yet sent */
     82static struct sclp_vt220_request *sclp_vt220_current_request;
     83
     84/* Number of characters in current request buffer */
     85static int sclp_vt220_buffered_chars;
     86
     87/* Counter controlling core driver initialization. */
     88static int __initdata sclp_vt220_init_count;
     89
     90/* Flag indicating that sclp_vt220_current_request should really
     91 * have been already queued but wasn't because the SCLP was processing
     92 * another buffer */
     93static int sclp_vt220_flush_later;
     94
     95static void sclp_vt220_receiver_fn(struct evbuf_header *evbuf);
     96static int __sclp_vt220_emit(struct sclp_vt220_request *request);
     97static void sclp_vt220_emit_current(void);
     98
     99/* Registration structure for SCLP output event buffers */
    100static struct sclp_register sclp_vt220_register = {
    101	.send_mask		= EVTYP_VT220MSG_MASK,
    102};
    103
    104/* Registration structure for SCLP input event buffers */
    105static struct sclp_register sclp_vt220_register_input = {
    106	.receive_mask		= EVTYP_VT220MSG_MASK,
    107	.receiver_fn		= sclp_vt220_receiver_fn,
    108};
    109
    110
    111/*
    112 * Put provided request buffer back into queue and check emit pending
    113 * buffers if necessary.
    114 */
    115static void
    116sclp_vt220_process_queue(struct sclp_vt220_request *request)
    117{
    118	unsigned long flags;
    119	void *page;
    120
    121	do {
    122		/* Put buffer back to list of empty buffers */
    123		page = request->sclp_req.sccb;
    124		spin_lock_irqsave(&sclp_vt220_lock, flags);
    125		/* Move request from outqueue to empty queue */
    126		list_del(&request->list);
    127		list_add_tail((struct list_head *) page, &sclp_vt220_empty);
    128		/* Check if there is a pending buffer on the out queue. */
    129		request = NULL;
    130		if (!list_empty(&sclp_vt220_outqueue))
    131			request = list_entry(sclp_vt220_outqueue.next,
    132					     struct sclp_vt220_request, list);
    133		if (!request) {
    134			sclp_vt220_queue_running = 0;
    135			spin_unlock_irqrestore(&sclp_vt220_lock, flags);
    136			break;
    137		}
    138		spin_unlock_irqrestore(&sclp_vt220_lock, flags);
    139	} while (__sclp_vt220_emit(request));
    140	if (request == NULL && sclp_vt220_flush_later)
    141		sclp_vt220_emit_current();
    142	tty_port_tty_wakeup(&sclp_vt220_port);
    143}
    144
    145#define SCLP_BUFFER_MAX_RETRY		1
    146
    147/*
    148 * Callback through which the result of a write request is reported by the
    149 * SCLP.
    150 */
    151static void
    152sclp_vt220_callback(struct sclp_req *request, void *data)
    153{
    154	struct sclp_vt220_request *vt220_request;
    155	struct sclp_vt220_sccb *sccb;
    156
    157	vt220_request = (struct sclp_vt220_request *) data;
    158	if (request->status == SCLP_REQ_FAILED) {
    159		sclp_vt220_process_queue(vt220_request);
    160		return;
    161	}
    162	sccb = (struct sclp_vt220_sccb *) vt220_request->sclp_req.sccb;
    163
    164	/* Check SCLP response code and choose suitable action	*/
    165	switch (sccb->header.response_code) {
    166	case 0x0020 :
    167		break;
    168
    169	case 0x05f0: /* Target resource in improper state */
    170		break;
    171
    172	case 0x0340: /* Contained SCLP equipment check */
    173		if (++vt220_request->retry_count > SCLP_BUFFER_MAX_RETRY)
    174			break;
    175		/* Remove processed buffers and requeue rest */
    176		if (sclp_remove_processed((struct sccb_header *) sccb) > 0) {
    177			/* Not all buffers were processed */
    178			sccb->header.response_code = 0x0000;
    179			vt220_request->sclp_req.status = SCLP_REQ_FILLED;
    180			if (sclp_add_request(request) == 0)
    181				return;
    182		}
    183		break;
    184
    185	case 0x0040: /* SCLP equipment check */
    186		if (++vt220_request->retry_count > SCLP_BUFFER_MAX_RETRY)
    187			break;
    188		sccb->header.response_code = 0x0000;
    189		vt220_request->sclp_req.status = SCLP_REQ_FILLED;
    190		if (sclp_add_request(request) == 0)
    191			return;
    192		break;
    193
    194	default:
    195		break;
    196	}
    197	sclp_vt220_process_queue(vt220_request);
    198}
    199
    200/*
    201 * Emit vt220 request buffer to SCLP. Return zero on success, non-zero
    202 * otherwise.
    203 */
    204static int
    205__sclp_vt220_emit(struct sclp_vt220_request *request)
    206{
    207	request->sclp_req.command = SCLP_CMDW_WRITE_EVENT_DATA;
    208	request->sclp_req.status = SCLP_REQ_FILLED;
    209	request->sclp_req.callback = sclp_vt220_callback;
    210	request->sclp_req.callback_data = (void *) request;
    211
    212	return sclp_add_request(&request->sclp_req);
    213}
    214
    215/*
    216 * Queue and emit current request.
    217 */
    218static void
    219sclp_vt220_emit_current(void)
    220{
    221	unsigned long flags;
    222	struct sclp_vt220_request *request;
    223	struct sclp_vt220_sccb *sccb;
    224
    225	spin_lock_irqsave(&sclp_vt220_lock, flags);
    226	if (sclp_vt220_current_request) {
    227		sccb = (struct sclp_vt220_sccb *) 
    228				sclp_vt220_current_request->sclp_req.sccb;
    229		/* Only emit buffers with content */
    230		if (sccb->header.length != sizeof(struct sclp_vt220_sccb)) {
    231			list_add_tail(&sclp_vt220_current_request->list,
    232				      &sclp_vt220_outqueue);
    233			sclp_vt220_current_request = NULL;
    234			del_timer(&sclp_vt220_timer);
    235		}
    236		sclp_vt220_flush_later = 0;
    237	}
    238	if (sclp_vt220_queue_running)
    239		goto out_unlock;
    240	if (list_empty(&sclp_vt220_outqueue))
    241		goto out_unlock;
    242	request = list_first_entry(&sclp_vt220_outqueue,
    243				   struct sclp_vt220_request, list);
    244	sclp_vt220_queue_running = 1;
    245	spin_unlock_irqrestore(&sclp_vt220_lock, flags);
    246
    247	if (__sclp_vt220_emit(request))
    248		sclp_vt220_process_queue(request);
    249	return;
    250out_unlock:
    251	spin_unlock_irqrestore(&sclp_vt220_lock, flags);
    252}
    253
    254#define SCLP_NORMAL_WRITE	0x00
    255
    256/*
    257 * Helper function to initialize a page with the sclp request structure.
    258 */
    259static struct sclp_vt220_request *
    260sclp_vt220_initialize_page(void *page)
    261{
    262	struct sclp_vt220_request *request;
    263	struct sclp_vt220_sccb *sccb;
    264
    265	/* Place request structure at end of page */
    266	request = ((struct sclp_vt220_request *)
    267			((addr_t) page + PAGE_SIZE)) - 1;
    268	request->retry_count = 0;
    269	request->sclp_req.sccb = page;
    270	/* SCCB goes at start of page */
    271	sccb = (struct sclp_vt220_sccb *) page;
    272	memset((void *) sccb, 0, sizeof(struct sclp_vt220_sccb));
    273	sccb->header.length = sizeof(struct sclp_vt220_sccb);
    274	sccb->header.function_code = SCLP_NORMAL_WRITE;
    275	sccb->header.response_code = 0x0000;
    276	sccb->evbuf.type = EVTYP_VT220MSG;
    277	sccb->evbuf.length = sizeof(struct evbuf_header);
    278
    279	return request;
    280}
    281
    282static inline unsigned int
    283sclp_vt220_space_left(struct sclp_vt220_request *request)
    284{
    285	struct sclp_vt220_sccb *sccb;
    286	sccb = (struct sclp_vt220_sccb *) request->sclp_req.sccb;
    287	return PAGE_SIZE - sizeof(struct sclp_vt220_request) -
    288	       sccb->header.length;
    289}
    290
    291static inline unsigned int
    292sclp_vt220_chars_stored(struct sclp_vt220_request *request)
    293{
    294	struct sclp_vt220_sccb *sccb;
    295	sccb = (struct sclp_vt220_sccb *) request->sclp_req.sccb;
    296	return sccb->evbuf.length - sizeof(struct evbuf_header);
    297}
    298
    299/*
    300 * Add msg to buffer associated with request. Return the number of characters
    301 * added.
    302 */
    303static int
    304sclp_vt220_add_msg(struct sclp_vt220_request *request,
    305		   const unsigned char *msg, int count, int convertlf)
    306{
    307	struct sclp_vt220_sccb *sccb;
    308	void *buffer;
    309	unsigned char c;
    310	int from;
    311	int to;
    312
    313	if (count > sclp_vt220_space_left(request))
    314		count = sclp_vt220_space_left(request);
    315	if (count <= 0)
    316		return 0;
    317
    318	sccb = (struct sclp_vt220_sccb *) request->sclp_req.sccb;
    319	buffer = (void *) ((addr_t) sccb + sccb->header.length);
    320
    321	if (convertlf) {
    322		/* Perform Linefeed conversion (0x0a -> 0x0a 0x0d)*/
    323		for (from=0, to=0;
    324		     (from < count) && (to < sclp_vt220_space_left(request));
    325		     from++) {
    326			/* Retrieve character */
    327			c = msg[from];
    328			/* Perform conversion */
    329			if (c == 0x0a) {
    330				if (to + 1 < sclp_vt220_space_left(request)) {
    331					((unsigned char *) buffer)[to++] = c;
    332					((unsigned char *) buffer)[to++] = 0x0d;
    333				} else
    334					break;
    335
    336			} else
    337				((unsigned char *) buffer)[to++] = c;
    338		}
    339		sccb->header.length += to;
    340		sccb->evbuf.length += to;
    341		return from;
    342	} else {
    343		memcpy(buffer, (const void *) msg, count);
    344		sccb->header.length += count;
    345		sccb->evbuf.length += count;
    346		return count;
    347	}
    348}
    349
    350/*
    351 * Emit buffer after having waited long enough for more data to arrive.
    352 */
    353static void
    354sclp_vt220_timeout(struct timer_list *unused)
    355{
    356	sclp_vt220_emit_current();
    357}
    358
    359#define BUFFER_MAX_DELAY	HZ/20
    360
    361/*
    362 * Drop oldest console buffer if sclp_con_drop is set
    363 */
    364static int
    365sclp_vt220_drop_buffer(void)
    366{
    367	struct list_head *list;
    368	struct sclp_vt220_request *request;
    369	void *page;
    370
    371	if (!sclp_console_drop)
    372		return 0;
    373	list = sclp_vt220_outqueue.next;
    374	if (sclp_vt220_queue_running)
    375		/* The first element is in I/O */
    376		list = list->next;
    377	if (list == &sclp_vt220_outqueue)
    378		return 0;
    379	list_del(list);
    380	request = list_entry(list, struct sclp_vt220_request, list);
    381	page = request->sclp_req.sccb;
    382	list_add_tail((struct list_head *) page, &sclp_vt220_empty);
    383	return 1;
    384}
    385
    386/* 
    387 * Internal implementation of the write function. Write COUNT bytes of data
    388 * from memory at BUF
    389 * to the SCLP interface. In case that the data does not fit into the current
    390 * write buffer, emit the current one and allocate a new one. If there are no
    391 * more empty buffers available, wait until one gets emptied. If DO_SCHEDULE
    392 * is non-zero, the buffer will be scheduled for emitting after a timeout -
    393 * otherwise the user has to explicitly call the flush function.
    394 * A non-zero CONVERTLF parameter indicates that 0x0a characters in the message
    395 * buffer should be converted to 0x0a 0x0d. After completion, return the number
    396 * of bytes written.
    397 */
    398static int
    399__sclp_vt220_write(const unsigned char *buf, int count, int do_schedule,
    400		   int convertlf, int may_fail)
    401{
    402	unsigned long flags;
    403	void *page;
    404	int written;
    405	int overall_written;
    406
    407	if (count <= 0)
    408		return 0;
    409	overall_written = 0;
    410	spin_lock_irqsave(&sclp_vt220_lock, flags);
    411	do {
    412		/* Create an sclp output buffer if none exists yet */
    413		if (sclp_vt220_current_request == NULL) {
    414			if (list_empty(&sclp_vt220_empty))
    415				sclp_console_full++;
    416			while (list_empty(&sclp_vt220_empty)) {
    417				if (may_fail)
    418					goto out;
    419				if (sclp_vt220_drop_buffer())
    420					break;
    421				spin_unlock_irqrestore(&sclp_vt220_lock, flags);
    422
    423				sclp_sync_wait();
    424				spin_lock_irqsave(&sclp_vt220_lock, flags);
    425			}
    426			page = (void *) sclp_vt220_empty.next;
    427			list_del((struct list_head *) page);
    428			sclp_vt220_current_request =
    429				sclp_vt220_initialize_page(page);
    430		}
    431		/* Try to write the string to the current request buffer */
    432		written = sclp_vt220_add_msg(sclp_vt220_current_request,
    433					     buf, count, convertlf);
    434		overall_written += written;
    435		if (written == count)
    436			break;
    437		/*
    438		 * Not all characters could be written to the current
    439		 * output buffer. Emit the buffer, create a new buffer
    440		 * and then output the rest of the string.
    441		 */
    442		spin_unlock_irqrestore(&sclp_vt220_lock, flags);
    443		sclp_vt220_emit_current();
    444		spin_lock_irqsave(&sclp_vt220_lock, flags);
    445		buf += written;
    446		count -= written;
    447	} while (count > 0);
    448	/* Setup timer to output current console buffer after some time */
    449	if (sclp_vt220_current_request != NULL &&
    450	    !timer_pending(&sclp_vt220_timer) && do_schedule) {
    451		sclp_vt220_timer.expires = jiffies + BUFFER_MAX_DELAY;
    452		add_timer(&sclp_vt220_timer);
    453	}
    454out:
    455	spin_unlock_irqrestore(&sclp_vt220_lock, flags);
    456	return overall_written;
    457}
    458
    459/*
    460 * This routine is called by the kernel to write a series of
    461 * characters to the tty device.  The characters may come from
    462 * user space or kernel space.  This routine will return the
    463 * number of characters actually accepted for writing.
    464 */
    465static int
    466sclp_vt220_write(struct tty_struct *tty, const unsigned char *buf, int count)
    467{
    468	return __sclp_vt220_write(buf, count, 1, 0, 1);
    469}
    470
    471#define SCLP_VT220_SESSION_ENDED	0x01
    472#define	SCLP_VT220_SESSION_STARTED	0x80
    473#define SCLP_VT220_SESSION_DATA		0x00
    474
    475#ifdef CONFIG_MAGIC_SYSRQ
    476
    477static int sysrq_pressed;
    478static struct sysrq_work sysrq;
    479
    480static void sclp_vt220_reset_session(void)
    481{
    482	sysrq_pressed = 0;
    483}
    484
    485static void sclp_vt220_handle_input(const char *buffer, unsigned int count)
    486{
    487	int i;
    488
    489	for (i = 0; i < count; i++) {
    490		/* Handle magic sys request */
    491		if (buffer[i] == ('O' ^ 0100)) { /* CTRL-O */
    492			/*
    493			 * If pressed again, reset sysrq_pressed
    494			 * and flip CTRL-O character
    495			 */
    496			sysrq_pressed = !sysrq_pressed;
    497			if (sysrq_pressed)
    498				continue;
    499		} else if (sysrq_pressed) {
    500			sysrq.key = buffer[i];
    501			schedule_sysrq_work(&sysrq);
    502			sysrq_pressed = 0;
    503			continue;
    504		}
    505		tty_insert_flip_char(&sclp_vt220_port, buffer[i], 0);
    506	}
    507}
    508
    509#else
    510
    511static void sclp_vt220_reset_session(void)
    512{
    513}
    514
    515static void sclp_vt220_handle_input(const char *buffer, unsigned int count)
    516{
    517	tty_insert_flip_string(&sclp_vt220_port, buffer, count);
    518}
    519
    520#endif
    521
    522/*
    523 * Called by the SCLP to report incoming event buffers.
    524 */
    525static void
    526sclp_vt220_receiver_fn(struct evbuf_header *evbuf)
    527{
    528	char *buffer;
    529	unsigned int count;
    530
    531	buffer = (char *) ((addr_t) evbuf + sizeof(struct evbuf_header));
    532	count = evbuf->length - sizeof(struct evbuf_header);
    533
    534	switch (*buffer) {
    535	case SCLP_VT220_SESSION_ENDED:
    536	case SCLP_VT220_SESSION_STARTED:
    537		sclp_vt220_reset_session();
    538		break;
    539	case SCLP_VT220_SESSION_DATA:
    540		/* Send input to line discipline */
    541		buffer++;
    542		count--;
    543		sclp_vt220_handle_input(buffer, count);
    544		tty_flip_buffer_push(&sclp_vt220_port);
    545		break;
    546	}
    547}
    548
    549/*
    550 * This routine is called when a particular tty device is opened.
    551 */
    552static int
    553sclp_vt220_open(struct tty_struct *tty, struct file *filp)
    554{
    555	if (tty->count == 1) {
    556		tty_port_tty_set(&sclp_vt220_port, tty);
    557		if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
    558			tty->winsize.ws_row = 24;
    559			tty->winsize.ws_col = 80;
    560		}
    561	}
    562	return 0;
    563}
    564
    565/*
    566 * This routine is called when a particular tty device is closed.
    567 */
    568static void
    569sclp_vt220_close(struct tty_struct *tty, struct file *filp)
    570{
    571	if (tty->count == 1)
    572		tty_port_tty_set(&sclp_vt220_port, NULL);
    573}
    574
    575/*
    576 * This routine is called by the kernel to write a single
    577 * character to the tty device.  If the kernel uses this routine,
    578 * it must call the flush_chars() routine (if defined) when it is
    579 * done stuffing characters into the driver.
    580 */
    581static int
    582sclp_vt220_put_char(struct tty_struct *tty, unsigned char ch)
    583{
    584	return __sclp_vt220_write(&ch, 1, 0, 0, 1);
    585}
    586
    587/*
    588 * This routine is called by the kernel after it has written a
    589 * series of characters to the tty device using put_char().  
    590 */
    591static void
    592sclp_vt220_flush_chars(struct tty_struct *tty)
    593{
    594	if (!sclp_vt220_queue_running)
    595		sclp_vt220_emit_current();
    596	else
    597		sclp_vt220_flush_later = 1;
    598}
    599
    600/*
    601 * This routine returns the numbers of characters the tty driver
    602 * will accept for queuing to be written.  This number is subject
    603 * to change as output buffers get emptied, or if the output flow
    604 * control is acted.
    605 */
    606static unsigned int
    607sclp_vt220_write_room(struct tty_struct *tty)
    608{
    609	unsigned long flags;
    610	struct list_head *l;
    611	unsigned int count;
    612
    613	spin_lock_irqsave(&sclp_vt220_lock, flags);
    614	count = 0;
    615	if (sclp_vt220_current_request != NULL)
    616		count = sclp_vt220_space_left(sclp_vt220_current_request);
    617	list_for_each(l, &sclp_vt220_empty)
    618		count += SCLP_VT220_MAX_CHARS_PER_BUFFER;
    619	spin_unlock_irqrestore(&sclp_vt220_lock, flags);
    620	return count;
    621}
    622
    623/*
    624 * Return number of buffered chars.
    625 */
    626static unsigned int
    627sclp_vt220_chars_in_buffer(struct tty_struct *tty)
    628{
    629	unsigned long flags;
    630	struct list_head *l;
    631	struct sclp_vt220_request *r;
    632	unsigned int count = 0;
    633
    634	spin_lock_irqsave(&sclp_vt220_lock, flags);
    635	if (sclp_vt220_current_request != NULL)
    636		count = sclp_vt220_chars_stored(sclp_vt220_current_request);
    637	list_for_each(l, &sclp_vt220_outqueue) {
    638		r = list_entry(l, struct sclp_vt220_request, list);
    639		count += sclp_vt220_chars_stored(r);
    640	}
    641	spin_unlock_irqrestore(&sclp_vt220_lock, flags);
    642	return count;
    643}
    644
    645/*
    646 * Pass on all buffers to the hardware. Return only when there are no more
    647 * buffers pending.
    648 */
    649static void
    650sclp_vt220_flush_buffer(struct tty_struct *tty)
    651{
    652	sclp_vt220_emit_current();
    653}
    654
    655/* Release allocated pages. */
    656static void __init __sclp_vt220_free_pages(void)
    657{
    658	struct list_head *page, *p;
    659
    660	list_for_each_safe(page, p, &sclp_vt220_empty) {
    661		list_del(page);
    662		free_page((unsigned long) page);
    663	}
    664}
    665
    666/* Release memory and unregister from sclp core. Controlled by init counting -
    667 * only the last invoker will actually perform these actions. */
    668static void __init __sclp_vt220_cleanup(void)
    669{
    670	sclp_vt220_init_count--;
    671	if (sclp_vt220_init_count != 0)
    672		return;
    673	sclp_unregister(&sclp_vt220_register);
    674	__sclp_vt220_free_pages();
    675	tty_port_destroy(&sclp_vt220_port);
    676}
    677
    678/* Allocate buffer pages and register with sclp core. Controlled by init
    679 * counting - only the first invoker will actually perform these actions. */
    680static int __init __sclp_vt220_init(int num_pages)
    681{
    682	void *page;
    683	int i;
    684	int rc;
    685
    686	sclp_vt220_init_count++;
    687	if (sclp_vt220_init_count != 1)
    688		return 0;
    689	timer_setup(&sclp_vt220_timer, sclp_vt220_timeout, 0);
    690	tty_port_init(&sclp_vt220_port);
    691	sclp_vt220_current_request = NULL;
    692	sclp_vt220_buffered_chars = 0;
    693	sclp_vt220_flush_later = 0;
    694
    695	/* Allocate pages for output buffering */
    696	rc = -ENOMEM;
    697	for (i = 0; i < num_pages; i++) {
    698		page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
    699		if (!page)
    700			goto out;
    701		list_add_tail(page, &sclp_vt220_empty);
    702	}
    703	rc = sclp_register(&sclp_vt220_register);
    704out:
    705	if (rc) {
    706		__sclp_vt220_free_pages();
    707		sclp_vt220_init_count--;
    708		tty_port_destroy(&sclp_vt220_port);
    709	}
    710	return rc;
    711}
    712
    713static const struct tty_operations sclp_vt220_ops = {
    714	.open = sclp_vt220_open,
    715	.close = sclp_vt220_close,
    716	.write = sclp_vt220_write,
    717	.put_char = sclp_vt220_put_char,
    718	.flush_chars = sclp_vt220_flush_chars,
    719	.write_room = sclp_vt220_write_room,
    720	.chars_in_buffer = sclp_vt220_chars_in_buffer,
    721	.flush_buffer = sclp_vt220_flush_buffer,
    722};
    723
    724/*
    725 * Register driver with SCLP and Linux and initialize internal tty structures.
    726 */
    727static int __init sclp_vt220_tty_init(void)
    728{
    729	struct tty_driver *driver;
    730	int rc;
    731
    732	/* Note: we're not testing for CONSOLE_IS_SCLP here to preserve
    733	 * symmetry between VM and LPAR systems regarding ttyS1. */
    734	driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW);
    735	if (IS_ERR(driver))
    736		return PTR_ERR(driver);
    737	rc = __sclp_vt220_init(MAX_KMEM_PAGES);
    738	if (rc)
    739		goto out_driver;
    740
    741	driver->driver_name = SCLP_VT220_DRIVER_NAME;
    742	driver->name = SCLP_VT220_DEVICE_NAME;
    743	driver->major = SCLP_VT220_MAJOR;
    744	driver->minor_start = SCLP_VT220_MINOR;
    745	driver->type = TTY_DRIVER_TYPE_SYSTEM;
    746	driver->subtype = SYSTEM_TYPE_TTY;
    747	driver->init_termios = tty_std_termios;
    748	tty_set_operations(driver, &sclp_vt220_ops);
    749	tty_port_link_device(&sclp_vt220_port, driver, 0);
    750
    751	rc = tty_register_driver(driver);
    752	if (rc)
    753		goto out_init;
    754	rc = sclp_register(&sclp_vt220_register_input);
    755	if (rc)
    756		goto out_reg;
    757	sclp_vt220_driver = driver;
    758	return 0;
    759
    760out_reg:
    761	tty_unregister_driver(driver);
    762out_init:
    763	__sclp_vt220_cleanup();
    764out_driver:
    765	tty_driver_kref_put(driver);
    766	return rc;
    767}
    768__initcall(sclp_vt220_tty_init);
    769
    770#ifdef CONFIG_SCLP_VT220_CONSOLE
    771
    772static void
    773sclp_vt220_con_write(struct console *con, const char *buf, unsigned int count)
    774{
    775	__sclp_vt220_write((const unsigned char *) buf, count, 1, 1, 0);
    776}
    777
    778static struct tty_driver *
    779sclp_vt220_con_device(struct console *c, int *index)
    780{
    781	*index = 0;
    782	return sclp_vt220_driver;
    783}
    784
    785/*
    786 * This panic/reboot notifier runs in atomic context, so
    787 * locking restrictions apply to prevent potential lockups.
    788 */
    789static int
    790sclp_vt220_notify(struct notifier_block *self,
    791			  unsigned long event, void *data)
    792{
    793	unsigned long flags;
    794
    795	if (spin_is_locked(&sclp_vt220_lock))
    796		return NOTIFY_DONE;
    797
    798	sclp_vt220_emit_current();
    799
    800	spin_lock_irqsave(&sclp_vt220_lock, flags);
    801	del_timer(&sclp_vt220_timer);
    802	while (sclp_vt220_queue_running) {
    803		spin_unlock_irqrestore(&sclp_vt220_lock, flags);
    804		sclp_sync_wait();
    805		spin_lock_irqsave(&sclp_vt220_lock, flags);
    806	}
    807	spin_unlock_irqrestore(&sclp_vt220_lock, flags);
    808
    809	return NOTIFY_DONE;
    810}
    811
    812static struct notifier_block on_panic_nb = {
    813	.notifier_call = sclp_vt220_notify,
    814	.priority = INT_MIN + 1, /* run the callback late */
    815};
    816
    817static struct notifier_block on_reboot_nb = {
    818	.notifier_call = sclp_vt220_notify,
    819	.priority = INT_MIN + 1, /* run the callback late */
    820};
    821
    822/* Structure needed to register with printk */
    823static struct console sclp_vt220_console =
    824{
    825	.name = SCLP_VT220_CONSOLE_NAME,
    826	.write = sclp_vt220_con_write,
    827	.device = sclp_vt220_con_device,
    828	.flags = CON_PRINTBUFFER,
    829	.index = SCLP_VT220_CONSOLE_INDEX
    830};
    831
    832static int __init
    833sclp_vt220_con_init(void)
    834{
    835	int rc;
    836
    837	rc = __sclp_vt220_init(sclp_console_pages);
    838	if (rc)
    839		return rc;
    840	/* Attach linux console */
    841	atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
    842	register_reboot_notifier(&on_reboot_nb);
    843	register_console(&sclp_vt220_console);
    844	return 0;
    845}
    846
    847console_initcall(sclp_vt220_con_init);
    848#endif /* CONFIG_SCLP_VT220_CONSOLE */
    849