linux/drivers/tty/hvc/hvc_console.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2001 Anton Blanchard <[email protected]>, IBM
 * Copyright (C) 2001 Paul Mackerras <[email protected]>, IBM
 * Copyright (C) 2004 Benjamin Herrenschmidt <[email protected]>, IBM Corp.
 * Copyright (C) 2004 IBM Corporation
 *
 * Additional Author(s):
 *  Ryan S. Arnold <[email protected]>
 */

#include <linux/console.h>
#include <linux/cpumask.h>
#include <linux/init.h>
#include <linux/kbd_kern.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/list.h>
#include <linux/major.h>
#include <linux/atomic.h>
#include <linux/sysrq.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/sched.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/freezer.h>
#include <linux/slab.h>
#include <linux/serial_core.h>

#include <linux/uaccess.h>

#include "hvc_console.h"

#define HVC_MAJOR
#define HVC_MINOR

/*
 * Wait this long per iteration while trying to push buffered data to the
 * hypervisor before allowing the tty to complete a close operation.
 */
#define HVC_CLOSE_WAIT

/*
 * These sizes are most efficient for vio, because they are the
 * native transfer size. We could make them selectable in the
 * future to better deal with backends that want other buffer sizes.
 */
#define N_OUTBUF
#define N_INBUF

#define __ALIGNED__

static struct tty_driver *hvc_driver;
static struct task_struct *hvc_task;

/* Picks up late kicks after list walk but before schedule() */
static int hvc_kicked;

/* hvc_init is triggered from hvc_alloc, i.e. only when actually used */
static atomic_t hvc_needs_init __read_mostly =;

static int hvc_init(void);

#ifdef CONFIG_MAGIC_SYSRQ
static int sysrq_pressed;
#endif

/* dynamic list of hvc_struct instances */
static LIST_HEAD(hvc_structs);

/*
 * Protect the list of hvc_struct instances from inserts and removals during
 * list traversal.
 */
static DEFINE_MUTEX(hvc_structs_mutex);

/*
 * This value is used to assign a tty->index value to a hvc_struct based
 * upon order of exposure via hvc_probe(), when we can not match it to
 * a console candidate registered with hvc_instantiate().
 */
static int last_hvc =;

/*
 * Do not call this function with either the hvc_structs_mutex or the hvc_struct
 * lock held.  If successful, this function increments the kref reference
 * count against the target hvc_struct so it should be released when finished.
 */
static struct hvc_struct *hvc_get_by_index(int index)
{}

static int __hvc_flush(const struct hv_ops *ops, uint32_t vtermno, bool wait)
{}

static int hvc_console_flush(const struct hv_ops *ops, uint32_t vtermno)
{}

/*
 * Wait for the console to flush before writing more to it. This sleeps.
 */
static int hvc_flush(struct hvc_struct *hp)
{}

/*
 * Initial console vtermnos for console API usage prior to full console
 * initialization.  Any vty adapter outside this range will not have usable
 * console interfaces but can still be used as a tty device.  This has to be
 * static because kmalloc will not work during early console init.
 */
static const struct hv_ops *cons_ops[MAX_NR_HVC_CONSOLES];
static uint32_t vtermnos[MAX_NR_HVC_CONSOLES] =;

/*
 * Console APIs, NOT TTY.  These APIs are available immediately when
 * hvc_console_setup() finds adapters.
 */

static void hvc_console_print(struct console *co, const char *b,
			      unsigned count)
{}

static struct tty_driver *hvc_console_device(struct console *c, int *index)
{}

static int hvc_console_setup(struct console *co, char *options)
{}

static struct console hvc_console =;

/*
 * Early console initialization.  Precedes driver initialization.
 *
 * (1) we are first, and the user specified another driver
 * -- index will remain -1
 * (2) we are first and the user specified no driver
 * -- index will be set to 0, then we will fail setup.
 * (3)  we are first and the user specified our driver
 * -- index will be set to user specified driver, and we will fail
 * (4) we are after driver, and this initcall will register us
 * -- if the user didn't specify a driver then the console will match
 *
 * Note that for cases 2 and 3, we will match later when the io driver
 * calls hvc_instantiate() and call register again.
 */
static int __init hvc_console_init(void)
{}
console_initcall(hvc_console_init);

/* callback when the kboject ref count reaches zero. */
static void hvc_port_destruct(struct tty_port *port)
{}

static void hvc_check_console(int index)
{}

/*
 * hvc_instantiate() is an early console discovery method which locates
 * consoles * prior to the vio subsystem discovering them.  Hotplugged
 * vty adapters do NOT get an hvc_instantiate() callback since they
 * appear after early console init.
 */
int hvc_instantiate(uint32_t vtermno, int index, const struct hv_ops *ops)
{}
EXPORT_SYMBOL_GPL();

/* Wake the sleeping khvcd */
void hvc_kick(void)
{}
EXPORT_SYMBOL_GPL();

static void hvc_unthrottle(struct tty_struct *tty)
{}

static int hvc_install(struct tty_driver *driver, struct tty_struct *tty)
{}

/*
 * The TTY interface won't be used until after the vio layer has exposed the vty
 * adapter to the kernel.
 */
static int hvc_open(struct tty_struct *tty, struct file * filp)
{}

static void hvc_close(struct tty_struct *tty, struct file * filp)
{}

static void hvc_cleanup(struct tty_struct *tty)
{}

static void hvc_hangup(struct tty_struct *tty)
{}

/*
 * Push buffered characters whether they were just recently buffered or waiting
 * on a blocked hypervisor.  Call this function with hp->lock held.
 */
static int hvc_push(struct hvc_struct *hp)
{}

static ssize_t hvc_write(struct tty_struct *tty, const u8 *buf, size_t count)
{}

/**
 * hvc_set_winsz() - Resize the hvc tty terminal window.
 * @work:	work structure.
 *
 * The routine shall not be called within an atomic context because it
 * might sleep.
 *
 * Locking:	hp->lock
 */
static void hvc_set_winsz(struct work_struct *work)
{}

/*
 * This is actually a contract between the driver and the tty layer outlining
 * how much write room the driver can guarantee will be sent OR BUFFERED.  This
 * driver MUST honor the return value.
 */
static unsigned int hvc_write_room(struct tty_struct *tty)
{}

static unsigned int hvc_chars_in_buffer(struct tty_struct *tty)
{}

/*
 * timeout will vary between the MIN and MAX values defined here.  By default
 * and during console activity we will use a default MIN_TIMEOUT of 10.  When
 * the console is idle, we increase the timeout value on each pass through
 * msleep until we reach the max.  This may be noticeable as a brief (average
 * one second) delay on the console before the console responds to input when
 * there has been no input for some time.
 */
#define MIN_TIMEOUT
#define MAX_TIMEOUT
static u32 timeout =;

/*
 * Maximum number of bytes to get from the console driver if hvc_poll is
 * called from driver (and can't sleep). Any more than this and we break
 * and start polling with khvcd. This value was derived from an OpenBMC
 * console with the OPAL driver that results in about 0.25ms interrupts off
 * latency.
 */
#define HVC_ATOMIC_READ_MAX

#define HVC_POLL_READ
#define HVC_POLL_WRITE

static int __hvc_poll(struct hvc_struct *hp, bool may_sleep)
{}

int hvc_poll(struct hvc_struct *hp)
{}
EXPORT_SYMBOL_GPL();

/**
 * __hvc_resize() - Update terminal window size information.
 * @hp:		HVC console pointer
 * @ws:		Terminal window size structure
 *
 * Stores the specified window size information in the hvc structure of @hp.
 * The function schedule the tty resize update.
 *
 * Locking:	Locking free; the function MUST be called holding hp->lock
 */
void __hvc_resize(struct hvc_struct *hp, struct winsize ws)
{}
EXPORT_SYMBOL_GPL();

/*
 * This kthread is either polling or interrupt driven.  This is determined by
 * calling hvc_poll() who determines whether a console adapter support
 * interrupts.
 */
static int khvcd(void *unused)
{}

static int hvc_tiocmget(struct tty_struct *tty)
{}

static int hvc_tiocmset(struct tty_struct *tty,
			unsigned int set, unsigned int clear)
{}

#ifdef CONFIG_CONSOLE_POLL
static int hvc_poll_init(struct tty_driver *driver, int line, char *options)
{}

static int hvc_poll_get_char(struct tty_driver *driver, int line)
{}

static void hvc_poll_put_char(struct tty_driver *driver, int line, char ch)
{}
#endif

static const struct tty_operations hvc_ops =;

static const struct tty_port_operations hvc_port_ops =;

struct hvc_struct *hvc_alloc(uint32_t vtermno, int data,
			     const struct hv_ops *ops,
			     int outbuf_size)
{}
EXPORT_SYMBOL_GPL();

void hvc_remove(struct hvc_struct *hp)
{}
EXPORT_SYMBOL_GPL();

/* Driver initialization: called as soon as someone uses hvc_alloc(). */
static int hvc_init(void)
{}