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

vcc.c (22607B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* vcc.c: sun4v virtual channel concentrator
      3 *
      4 * Copyright (C) 2017 Oracle. All rights reserved.
      5 */
      6
      7#include <linux/delay.h>
      8#include <linux/interrupt.h>
      9#include <linux/module.h>
     10#include <linux/slab.h>
     11#include <linux/sysfs.h>
     12#include <linux/tty.h>
     13#include <linux/tty_flip.h>
     14#include <asm/vio.h>
     15#include <asm/ldc.h>
     16
     17MODULE_DESCRIPTION("Sun LDOM virtual console concentrator driver");
     18MODULE_LICENSE("GPL");
     19MODULE_VERSION("1.1");
     20
     21struct vcc_port {
     22	struct vio_driver_state vio;
     23
     24	spinlock_t lock;
     25	char *domain;
     26	struct tty_struct *tty;	/* only populated while dev is open */
     27	unsigned long index;	/* index into the vcc_table */
     28
     29	u64 refcnt;
     30	bool excl_locked;
     31
     32	bool removed;
     33
     34	/* This buffer is required to support the tty write_room interface
     35	 * and guarantee that any characters that the driver accepts will
     36	 * be eventually sent, either immediately or later.
     37	 */
     38	int chars_in_buffer;
     39	struct vio_vcc buffer;
     40
     41	struct timer_list rx_timer;
     42	struct timer_list tx_timer;
     43};
     44
     45/* Microseconds that thread will delay waiting for a vcc port ref */
     46#define VCC_REF_DELAY		100
     47
     48#define VCC_MAX_PORTS		1024
     49#define VCC_MINOR_START		0	/* must be zero */
     50#define VCC_BUFF_LEN		VIO_VCC_MTU_SIZE
     51
     52#define VCC_CTL_BREAK		-1
     53#define VCC_CTL_HUP		-2
     54
     55static struct tty_driver *vcc_tty_driver;
     56
     57static struct vcc_port *vcc_table[VCC_MAX_PORTS];
     58static DEFINE_SPINLOCK(vcc_table_lock);
     59
     60static unsigned int vcc_dbg;
     61static unsigned int vcc_dbg_ldc;
     62static unsigned int vcc_dbg_vio;
     63
     64module_param(vcc_dbg, uint, 0664);
     65module_param(vcc_dbg_ldc, uint, 0664);
     66module_param(vcc_dbg_vio, uint, 0664);
     67
     68#define VCC_DBG_DRV	0x1
     69#define VCC_DBG_LDC	0x2
     70#define VCC_DBG_PKT	0x4
     71
     72#define vccdbg(f, a...)						\
     73	do {							\
     74		if (vcc_dbg & VCC_DBG_DRV)			\
     75			pr_info(f, ## a);			\
     76	} while (0)						\
     77
     78#define vccdbgl(l)						\
     79	do {							\
     80		if (vcc_dbg & VCC_DBG_LDC)			\
     81			ldc_print(l);				\
     82	} while (0)						\
     83
     84#define vccdbgp(pkt)						\
     85	do {							\
     86		if (vcc_dbg & VCC_DBG_PKT) {			\
     87			int i;					\
     88			for (i = 0; i < pkt.tag.stype; i++)	\
     89				pr_info("[%c]", pkt.data[i]);	\
     90		}						\
     91	} while (0)						\
     92
     93/* Note: Be careful when adding flags to this line discipline.  Don't
     94 * add anything that will cause echoing or we'll go into recursive
     95 * loop echoing chars back and forth with the console drivers.
     96 */
     97static const struct ktermios vcc_tty_termios = {
     98	.c_iflag = IGNBRK | IGNPAR,
     99	.c_oflag = OPOST,
    100	.c_cflag = B38400 | CS8 | CREAD | HUPCL,
    101	.c_cc = INIT_C_CC,
    102	.c_ispeed = 38400,
    103	.c_ospeed = 38400
    104};
    105
    106/**
    107 * vcc_table_add() - Add VCC port to the VCC table
    108 * @port: pointer to the VCC port
    109 *
    110 * Return: index of the port in the VCC table on success,
    111 *	   -1 on failure
    112 */
    113static int vcc_table_add(struct vcc_port *port)
    114{
    115	unsigned long flags;
    116	int i;
    117
    118	spin_lock_irqsave(&vcc_table_lock, flags);
    119	for (i = VCC_MINOR_START; i < VCC_MAX_PORTS; i++) {
    120		if (!vcc_table[i]) {
    121			vcc_table[i] = port;
    122			break;
    123		}
    124	}
    125	spin_unlock_irqrestore(&vcc_table_lock, flags);
    126
    127	if (i < VCC_MAX_PORTS)
    128		return i;
    129	else
    130		return -1;
    131}
    132
    133/**
    134 * vcc_table_remove() - Removes a VCC port from the VCC table
    135 * @index: Index into the VCC table
    136 */
    137static void vcc_table_remove(unsigned long index)
    138{
    139	unsigned long flags;
    140
    141	if (WARN_ON(index >= VCC_MAX_PORTS))
    142		return;
    143
    144	spin_lock_irqsave(&vcc_table_lock, flags);
    145	vcc_table[index] = NULL;
    146	spin_unlock_irqrestore(&vcc_table_lock, flags);
    147}
    148
    149/**
    150 * vcc_get() - Gets a reference to VCC port
    151 * @index: Index into the VCC table
    152 * @excl: Indicates if an exclusive access is requested
    153 *
    154 * Return: reference to the VCC port, if found
    155 *	   NULL, if port not found
    156 */
    157static struct vcc_port *vcc_get(unsigned long index, bool excl)
    158{
    159	struct vcc_port *port;
    160	unsigned long flags;
    161
    162try_again:
    163	spin_lock_irqsave(&vcc_table_lock, flags);
    164
    165	port = vcc_table[index];
    166	if (!port) {
    167		spin_unlock_irqrestore(&vcc_table_lock, flags);
    168		return NULL;
    169	}
    170
    171	if (!excl) {
    172		if (port->excl_locked) {
    173			spin_unlock_irqrestore(&vcc_table_lock, flags);
    174			udelay(VCC_REF_DELAY);
    175			goto try_again;
    176		}
    177		port->refcnt++;
    178		spin_unlock_irqrestore(&vcc_table_lock, flags);
    179		return port;
    180	}
    181
    182	if (port->refcnt) {
    183		spin_unlock_irqrestore(&vcc_table_lock, flags);
    184		/* Threads wanting exclusive access will wait half the time,
    185		 * probably giving them higher priority in the case of
    186		 * multiple waiters.
    187		 */
    188		udelay(VCC_REF_DELAY/2);
    189		goto try_again;
    190	}
    191
    192	port->refcnt++;
    193	port->excl_locked = true;
    194	spin_unlock_irqrestore(&vcc_table_lock, flags);
    195
    196	return port;
    197}
    198
    199/**
    200 * vcc_put() - Returns a reference to VCC port
    201 * @port: pointer to VCC port
    202 * @excl: Indicates if the returned reference is an exclusive reference
    203 *
    204 * Note: It's the caller's responsibility to ensure the correct value
    205 *	 for the excl flag
    206 */
    207static void vcc_put(struct vcc_port *port, bool excl)
    208{
    209	unsigned long flags;
    210
    211	if (!port)
    212		return;
    213
    214	spin_lock_irqsave(&vcc_table_lock, flags);
    215
    216	/* check if caller attempted to put with the wrong flags */
    217	if (WARN_ON((excl && !port->excl_locked) ||
    218		    (!excl && port->excl_locked)))
    219		goto done;
    220
    221	port->refcnt--;
    222
    223	if (excl)
    224		port->excl_locked = false;
    225
    226done:
    227	spin_unlock_irqrestore(&vcc_table_lock, flags);
    228}
    229
    230/**
    231 * vcc_get_ne() - Get a non-exclusive reference to VCC port
    232 * @index: Index into the VCC table
    233 *
    234 * Gets a non-exclusive reference to VCC port, if it's not removed
    235 *
    236 * Return: pointer to the VCC port, if found
    237 *	   NULL, if port not found
    238 */
    239static struct vcc_port *vcc_get_ne(unsigned long index)
    240{
    241	struct vcc_port *port;
    242
    243	port = vcc_get(index, false);
    244
    245	if (port && port->removed) {
    246		vcc_put(port, false);
    247		return NULL;
    248	}
    249
    250	return port;
    251}
    252
    253static void vcc_kick_rx(struct vcc_port *port)
    254{
    255	struct vio_driver_state *vio = &port->vio;
    256
    257	assert_spin_locked(&port->lock);
    258
    259	if (!timer_pending(&port->rx_timer) && !port->removed) {
    260		disable_irq_nosync(vio->vdev->rx_irq);
    261		port->rx_timer.expires = (jiffies + 1);
    262		add_timer(&port->rx_timer);
    263	}
    264}
    265
    266static void vcc_kick_tx(struct vcc_port *port)
    267{
    268	assert_spin_locked(&port->lock);
    269
    270	if (!timer_pending(&port->tx_timer) && !port->removed) {
    271		port->tx_timer.expires = (jiffies + 1);
    272		add_timer(&port->tx_timer);
    273	}
    274}
    275
    276static int vcc_rx_check(struct tty_struct *tty, int size)
    277{
    278	if (WARN_ON(!tty || !tty->port))
    279		return 1;
    280
    281	/* tty_buffer_request_room won't sleep because it uses
    282	 * GFP_ATOMIC flag to allocate buffer
    283	 */
    284	if (test_bit(TTY_THROTTLED, &tty->flags) ||
    285	    (tty_buffer_request_room(tty->port, VCC_BUFF_LEN) < VCC_BUFF_LEN))
    286		return 0;
    287
    288	return 1;
    289}
    290
    291static int vcc_rx(struct tty_struct *tty, char *buf, int size)
    292{
    293	int len = 0;
    294
    295	if (WARN_ON(!tty || !tty->port))
    296		return len;
    297
    298	len = tty_insert_flip_string(tty->port, buf, size);
    299	if (len)
    300		tty_flip_buffer_push(tty->port);
    301
    302	return len;
    303}
    304
    305static int vcc_ldc_read(struct vcc_port *port)
    306{
    307	struct vio_driver_state *vio = &port->vio;
    308	struct tty_struct *tty;
    309	struct vio_vcc pkt;
    310	int rv = 0;
    311
    312	tty = port->tty;
    313	if (!tty) {
    314		rv = ldc_rx_reset(vio->lp);
    315		vccdbg("VCC: reset rx q: rv=%d\n", rv);
    316		goto done;
    317	}
    318
    319	/* Read as long as LDC has incoming data. */
    320	while (1) {
    321		if (!vcc_rx_check(tty, VIO_VCC_MTU_SIZE)) {
    322			vcc_kick_rx(port);
    323			break;
    324		}
    325
    326		vccdbgl(vio->lp);
    327
    328		rv = ldc_read(vio->lp, &pkt, sizeof(pkt));
    329		if (rv <= 0)
    330			break;
    331
    332		vccdbg("VCC: ldc_read()=%d\n", rv);
    333		vccdbg("TAG [%02x:%02x:%04x:%08x]\n",
    334		       pkt.tag.type, pkt.tag.stype,
    335		       pkt.tag.stype_env, pkt.tag.sid);
    336
    337		if (pkt.tag.type == VIO_TYPE_DATA) {
    338			vccdbgp(pkt);
    339			/* vcc_rx_check ensures memory availability */
    340			vcc_rx(tty, pkt.data, pkt.tag.stype);
    341		} else {
    342			pr_err("VCC: unknown msg [%02x:%02x:%04x:%08x]\n",
    343			       pkt.tag.type, pkt.tag.stype,
    344			       pkt.tag.stype_env, pkt.tag.sid);
    345			rv = -ECONNRESET;
    346			break;
    347		}
    348
    349		WARN_ON(rv != LDC_PACKET_SIZE);
    350	}
    351
    352done:
    353	return rv;
    354}
    355
    356static void vcc_rx_timer(struct timer_list *t)
    357{
    358	struct vcc_port *port = from_timer(port, t, rx_timer);
    359	struct vio_driver_state *vio;
    360	unsigned long flags;
    361	int rv;
    362
    363	spin_lock_irqsave(&port->lock, flags);
    364	port->rx_timer.expires = 0;
    365
    366	vio = &port->vio;
    367
    368	enable_irq(vio->vdev->rx_irq);
    369
    370	if (!port->tty || port->removed)
    371		goto done;
    372
    373	rv = vcc_ldc_read(port);
    374	if (rv == -ECONNRESET)
    375		vio_conn_reset(vio);
    376
    377done:
    378	spin_unlock_irqrestore(&port->lock, flags);
    379	vcc_put(port, false);
    380}
    381
    382static void vcc_tx_timer(struct timer_list *t)
    383{
    384	struct vcc_port *port = from_timer(port, t, tx_timer);
    385	struct vio_vcc *pkt;
    386	unsigned long flags;
    387	int tosend = 0;
    388	int rv;
    389
    390	spin_lock_irqsave(&port->lock, flags);
    391	port->tx_timer.expires = 0;
    392
    393	if (!port->tty || port->removed)
    394		goto done;
    395
    396	tosend = min(VCC_BUFF_LEN, port->chars_in_buffer);
    397	if (!tosend)
    398		goto done;
    399
    400	pkt = &port->buffer;
    401	pkt->tag.type = VIO_TYPE_DATA;
    402	pkt->tag.stype = tosend;
    403	vccdbgl(port->vio.lp);
    404
    405	rv = ldc_write(port->vio.lp, pkt, (VIO_TAG_SIZE + tosend));
    406	WARN_ON(!rv);
    407
    408	if (rv < 0) {
    409		vccdbg("VCC: ldc_write()=%d\n", rv);
    410		vcc_kick_tx(port);
    411	} else {
    412		struct tty_struct *tty = port->tty;
    413
    414		port->chars_in_buffer = 0;
    415		if (tty)
    416			tty_wakeup(tty);
    417	}
    418
    419done:
    420	spin_unlock_irqrestore(&port->lock, flags);
    421	vcc_put(port, false);
    422}
    423
    424/**
    425 * vcc_event() - LDC event processing engine
    426 * @arg: VCC private data
    427 * @event: LDC event
    428 *
    429 * Handles LDC events for VCC
    430 */
    431static void vcc_event(void *arg, int event)
    432{
    433	struct vio_driver_state *vio;
    434	struct vcc_port *port;
    435	unsigned long flags;
    436	int rv;
    437
    438	port = arg;
    439	vio = &port->vio;
    440
    441	spin_lock_irqsave(&port->lock, flags);
    442
    443	switch (event) {
    444	case LDC_EVENT_RESET:
    445	case LDC_EVENT_UP:
    446		vio_link_state_change(vio, event);
    447		break;
    448
    449	case LDC_EVENT_DATA_READY:
    450		rv = vcc_ldc_read(port);
    451		if (rv == -ECONNRESET)
    452			vio_conn_reset(vio);
    453		break;
    454
    455	default:
    456		pr_err("VCC: unexpected LDC event(%d)\n", event);
    457	}
    458
    459	spin_unlock_irqrestore(&port->lock, flags);
    460}
    461
    462static struct ldc_channel_config vcc_ldc_cfg = {
    463	.event		= vcc_event,
    464	.mtu		= VIO_VCC_MTU_SIZE,
    465	.mode		= LDC_MODE_RAW,
    466	.debug		= 0,
    467};
    468
    469/* Ordered from largest major to lowest */
    470static struct vio_version vcc_versions[] = {
    471	{ .major = 1, .minor = 0 },
    472};
    473
    474static struct tty_port_operations vcc_port_ops = { 0 };
    475
    476static ssize_t domain_show(struct device *dev,
    477			   struct device_attribute *attr,
    478			   char *buf)
    479{
    480	struct vcc_port *port;
    481	int rv;
    482
    483	port = dev_get_drvdata(dev);
    484	if (!port)
    485		return -ENODEV;
    486
    487	rv = scnprintf(buf, PAGE_SIZE, "%s\n", port->domain);
    488
    489	return rv;
    490}
    491
    492static int vcc_send_ctl(struct vcc_port *port, int ctl)
    493{
    494	struct vio_vcc pkt;
    495	int rv;
    496
    497	pkt.tag.type = VIO_TYPE_CTRL;
    498	pkt.tag.sid = ctl;
    499	pkt.tag.stype = 0;
    500
    501	rv = ldc_write(port->vio.lp, &pkt, sizeof(pkt.tag));
    502	WARN_ON(!rv);
    503	vccdbg("VCC: ldc_write(%ld)=%d\n", sizeof(pkt.tag), rv);
    504
    505	return rv;
    506}
    507
    508static ssize_t break_store(struct device *dev,
    509			   struct device_attribute *attr,
    510			   const char *buf, size_t count)
    511{
    512	struct vcc_port *port;
    513	unsigned long flags;
    514	int rv = count;
    515	int brk;
    516
    517	port = dev_get_drvdata(dev);
    518	if (!port)
    519		return -ENODEV;
    520
    521	spin_lock_irqsave(&port->lock, flags);
    522
    523	if (sscanf(buf, "%ud", &brk) != 1 || brk != 1)
    524		rv = -EINVAL;
    525	else if (vcc_send_ctl(port, VCC_CTL_BREAK) < 0)
    526		vcc_kick_tx(port);
    527
    528	spin_unlock_irqrestore(&port->lock, flags);
    529
    530	return rv;
    531}
    532
    533static DEVICE_ATTR_ADMIN_RO(domain);
    534static DEVICE_ATTR_WO(break);
    535
    536static struct attribute *vcc_sysfs_entries[] = {
    537	&dev_attr_domain.attr,
    538	&dev_attr_break.attr,
    539	NULL
    540};
    541
    542static struct attribute_group vcc_attribute_group = {
    543	.name = NULL,
    544	.attrs = vcc_sysfs_entries,
    545};
    546
    547/**
    548 * vcc_probe() - Initialize VCC port
    549 * @vdev: Pointer to VIO device of the new VCC port
    550 * @id: VIO device ID
    551 *
    552 * Initializes a VCC port to receive serial console data from
    553 * the guest domain. Sets up a TTY end point on the control
    554 * domain. Sets up VIO/LDC link between the guest & control
    555 * domain endpoints.
    556 *
    557 * Return: status of the probe
    558 */
    559static int vcc_probe(struct vio_dev *vdev, const struct vio_device_id *id)
    560{
    561	struct mdesc_handle *hp;
    562	struct vcc_port *port;
    563	struct device *dev;
    564	const char *domain;
    565	char *name;
    566	u64 node;
    567	int rv;
    568
    569	vccdbg("VCC: name=%s\n", dev_name(&vdev->dev));
    570
    571	if (!vcc_tty_driver) {
    572		pr_err("VCC: TTY driver not registered\n");
    573		return -ENODEV;
    574	}
    575
    576	port = kzalloc(sizeof(struct vcc_port), GFP_KERNEL);
    577	if (!port)
    578		return -ENOMEM;
    579
    580	name = kstrdup(dev_name(&vdev->dev), GFP_KERNEL);
    581
    582	rv = vio_driver_init(&port->vio, vdev, VDEV_CONSOLE_CON, vcc_versions,
    583			     ARRAY_SIZE(vcc_versions), NULL, name);
    584	if (rv)
    585		goto free_port;
    586
    587	port->vio.debug = vcc_dbg_vio;
    588	vcc_ldc_cfg.debug = vcc_dbg_ldc;
    589
    590	rv = vio_ldc_alloc(&port->vio, &vcc_ldc_cfg, port);
    591	if (rv)
    592		goto free_port;
    593
    594	spin_lock_init(&port->lock);
    595
    596	port->index = vcc_table_add(port);
    597	if (port->index == -1) {
    598		pr_err("VCC: no more TTY indices left for allocation\n");
    599		rv = -ENOMEM;
    600		goto free_ldc;
    601	}
    602
    603	/* Register the device using VCC table index as TTY index */
    604	dev = tty_register_device(vcc_tty_driver, port->index, &vdev->dev);
    605	if (IS_ERR(dev)) {
    606		rv = PTR_ERR(dev);
    607		goto free_table;
    608	}
    609
    610	hp = mdesc_grab();
    611
    612	node = vio_vdev_node(hp, vdev);
    613	if (node == MDESC_NODE_NULL) {
    614		rv = -ENXIO;
    615		mdesc_release(hp);
    616		goto unreg_tty;
    617	}
    618
    619	domain = mdesc_get_property(hp, node, "vcc-domain-name", NULL);
    620	if (!domain) {
    621		rv = -ENXIO;
    622		mdesc_release(hp);
    623		goto unreg_tty;
    624	}
    625	port->domain = kstrdup(domain, GFP_KERNEL);
    626
    627	mdesc_release(hp);
    628
    629	rv = sysfs_create_group(&vdev->dev.kobj, &vcc_attribute_group);
    630	if (rv)
    631		goto free_domain;
    632
    633	timer_setup(&port->rx_timer, vcc_rx_timer, 0);
    634	timer_setup(&port->tx_timer, vcc_tx_timer, 0);
    635
    636	dev_set_drvdata(&vdev->dev, port);
    637
    638	/* It's possible to receive IRQs in the middle of vio_port_up. Disable
    639	 * IRQs until the port is up.
    640	 */
    641	disable_irq_nosync(vdev->rx_irq);
    642	vio_port_up(&port->vio);
    643	enable_irq(vdev->rx_irq);
    644
    645	return 0;
    646
    647free_domain:
    648	kfree(port->domain);
    649unreg_tty:
    650	tty_unregister_device(vcc_tty_driver, port->index);
    651free_table:
    652	vcc_table_remove(port->index);
    653free_ldc:
    654	vio_ldc_free(&port->vio);
    655free_port:
    656	kfree(name);
    657	kfree(port);
    658
    659	return rv;
    660}
    661
    662/**
    663 * vcc_remove() - Terminate a VCC port
    664 * @vdev: Pointer to VIO device of the VCC port
    665 *
    666 * Terminates a VCC port. Sets up the teardown of TTY and
    667 * VIO/LDC link between guest and primary domains.
    668 *
    669 * Return: status of removal
    670 */
    671static void vcc_remove(struct vio_dev *vdev)
    672{
    673	struct vcc_port *port = dev_get_drvdata(&vdev->dev);
    674
    675	del_timer_sync(&port->rx_timer);
    676	del_timer_sync(&port->tx_timer);
    677
    678	/* If there's a process with the device open, do a synchronous
    679	 * hangup of the TTY. This *may* cause the process to call close
    680	 * asynchronously, but it's not guaranteed.
    681	 */
    682	if (port->tty)
    683		tty_vhangup(port->tty);
    684
    685	/* Get exclusive reference to VCC, ensures that there are no other
    686	 * clients to this port. This cannot fail.
    687	 */
    688	vcc_get(port->index, true);
    689
    690	tty_unregister_device(vcc_tty_driver, port->index);
    691
    692	del_timer_sync(&port->vio.timer);
    693	vio_ldc_free(&port->vio);
    694	sysfs_remove_group(&vdev->dev.kobj, &vcc_attribute_group);
    695	dev_set_drvdata(&vdev->dev, NULL);
    696	if (port->tty) {
    697		port->removed = true;
    698		vcc_put(port, true);
    699	} else {
    700		vcc_table_remove(port->index);
    701
    702		kfree(port->vio.name);
    703		kfree(port->domain);
    704		kfree(port);
    705	}
    706}
    707
    708static const struct vio_device_id vcc_match[] = {
    709	{
    710		.type = "vcc-port",
    711	},
    712	{},
    713};
    714MODULE_DEVICE_TABLE(vio, vcc_match);
    715
    716static struct vio_driver vcc_driver = {
    717	.id_table	= vcc_match,
    718	.probe		= vcc_probe,
    719	.remove		= vcc_remove,
    720	.name		= "vcc",
    721};
    722
    723static int vcc_open(struct tty_struct *tty, struct file *vcc_file)
    724{
    725	struct vcc_port *port;
    726
    727	if (tty->count > 1)
    728		return -EBUSY;
    729
    730	port = vcc_get_ne(tty->index);
    731	if (unlikely(!port)) {
    732		pr_err("VCC: open: Failed to find VCC port\n");
    733		return -ENODEV;
    734	}
    735
    736	if (unlikely(!port->vio.lp)) {
    737		pr_err("VCC: open: LDC channel not configured\n");
    738		vcc_put(port, false);
    739		return -EPIPE;
    740	}
    741	vccdbgl(port->vio.lp);
    742
    743	vcc_put(port, false);
    744
    745	if (unlikely(!tty->port)) {
    746		pr_err("VCC: open: TTY port not found\n");
    747		return -ENXIO;
    748	}
    749
    750	if (unlikely(!tty->port->ops)) {
    751		pr_err("VCC: open: TTY ops not defined\n");
    752		return -ENXIO;
    753	}
    754
    755	return tty_port_open(tty->port, tty, vcc_file);
    756}
    757
    758static void vcc_close(struct tty_struct *tty, struct file *vcc_file)
    759{
    760	if (unlikely(tty->count > 1))
    761		return;
    762
    763	if (unlikely(!tty->port)) {
    764		pr_err("VCC: close: TTY port not found\n");
    765		return;
    766	}
    767
    768	tty_port_close(tty->port, tty, vcc_file);
    769}
    770
    771static void vcc_ldc_hup(struct vcc_port *port)
    772{
    773	unsigned long flags;
    774
    775	spin_lock_irqsave(&port->lock, flags);
    776
    777	if (vcc_send_ctl(port, VCC_CTL_HUP) < 0)
    778		vcc_kick_tx(port);
    779
    780	spin_unlock_irqrestore(&port->lock, flags);
    781}
    782
    783static void vcc_hangup(struct tty_struct *tty)
    784{
    785	struct vcc_port *port;
    786
    787	port = vcc_get_ne(tty->index);
    788	if (unlikely(!port)) {
    789		pr_err("VCC: hangup: Failed to find VCC port\n");
    790		return;
    791	}
    792
    793	if (unlikely(!tty->port)) {
    794		pr_err("VCC: hangup: TTY port not found\n");
    795		vcc_put(port, false);
    796		return;
    797	}
    798
    799	vcc_ldc_hup(port);
    800
    801	vcc_put(port, false);
    802
    803	tty_port_hangup(tty->port);
    804}
    805
    806static int vcc_write(struct tty_struct *tty, const unsigned char *buf,
    807		     int count)
    808{
    809	struct vcc_port *port;
    810	struct vio_vcc *pkt;
    811	unsigned long flags;
    812	int total_sent = 0;
    813	int tosend = 0;
    814	int rv = -EINVAL;
    815
    816	port = vcc_get_ne(tty->index);
    817	if (unlikely(!port)) {
    818		pr_err("VCC: write: Failed to find VCC port");
    819		return -ENODEV;
    820	}
    821
    822	spin_lock_irqsave(&port->lock, flags);
    823
    824	pkt = &port->buffer;
    825	pkt->tag.type = VIO_TYPE_DATA;
    826
    827	while (count > 0) {
    828		/* Minimum of data to write and space available */
    829		tosend = min(count, (VCC_BUFF_LEN - port->chars_in_buffer));
    830
    831		if (!tosend)
    832			break;
    833
    834		memcpy(&pkt->data[port->chars_in_buffer], &buf[total_sent],
    835		       tosend);
    836		port->chars_in_buffer += tosend;
    837		pkt->tag.stype = tosend;
    838
    839		vccdbg("TAG [%02x:%02x:%04x:%08x]\n", pkt->tag.type,
    840		       pkt->tag.stype, pkt->tag.stype_env, pkt->tag.sid);
    841		vccdbg("DATA [%s]\n", pkt->data);
    842		vccdbgl(port->vio.lp);
    843
    844		/* Since we know we have enough room in VCC buffer for tosend
    845		 * we record that it was sent regardless of whether the
    846		 * hypervisor actually took it because we have it buffered.
    847		 */
    848		rv = ldc_write(port->vio.lp, pkt, (VIO_TAG_SIZE + tosend));
    849		vccdbg("VCC: write: ldc_write(%d)=%d\n",
    850		       (VIO_TAG_SIZE + tosend), rv);
    851
    852		total_sent += tosend;
    853		count -= tosend;
    854		if (rv < 0) {
    855			vcc_kick_tx(port);
    856			break;
    857		}
    858
    859		port->chars_in_buffer = 0;
    860	}
    861
    862	spin_unlock_irqrestore(&port->lock, flags);
    863
    864	vcc_put(port, false);
    865
    866	vccdbg("VCC: write: total=%d rv=%d", total_sent, rv);
    867
    868	return total_sent ? total_sent : rv;
    869}
    870
    871static unsigned int vcc_write_room(struct tty_struct *tty)
    872{
    873	struct vcc_port *port;
    874	unsigned int num;
    875
    876	port = vcc_get_ne(tty->index);
    877	if (unlikely(!port)) {
    878		pr_err("VCC: write_room: Failed to find VCC port\n");
    879		return 0;
    880	}
    881
    882	num = VCC_BUFF_LEN - port->chars_in_buffer;
    883
    884	vcc_put(port, false);
    885
    886	return num;
    887}
    888
    889static unsigned int vcc_chars_in_buffer(struct tty_struct *tty)
    890{
    891	struct vcc_port *port;
    892	unsigned int num;
    893
    894	port = vcc_get_ne(tty->index);
    895	if (unlikely(!port)) {
    896		pr_err("VCC: chars_in_buffer: Failed to find VCC port\n");
    897		return 0;
    898	}
    899
    900	num = port->chars_in_buffer;
    901
    902	vcc_put(port, false);
    903
    904	return num;
    905}
    906
    907static int vcc_break_ctl(struct tty_struct *tty, int state)
    908{
    909	struct vcc_port *port;
    910	unsigned long flags;
    911
    912	port = vcc_get_ne(tty->index);
    913	if (unlikely(!port)) {
    914		pr_err("VCC: break_ctl: Failed to find VCC port\n");
    915		return -ENODEV;
    916	}
    917
    918	/* Turn off break */
    919	if (state == 0) {
    920		vcc_put(port, false);
    921		return 0;
    922	}
    923
    924	spin_lock_irqsave(&port->lock, flags);
    925
    926	if (vcc_send_ctl(port, VCC_CTL_BREAK) < 0)
    927		vcc_kick_tx(port);
    928
    929	spin_unlock_irqrestore(&port->lock, flags);
    930
    931	vcc_put(port, false);
    932
    933	return 0;
    934}
    935
    936static int vcc_install(struct tty_driver *driver, struct tty_struct *tty)
    937{
    938	struct vcc_port *port_vcc;
    939	struct tty_port *port_tty;
    940	int ret;
    941
    942	if (tty->index >= VCC_MAX_PORTS)
    943		return -EINVAL;
    944
    945	ret = tty_standard_install(driver, tty);
    946	if (ret)
    947		return ret;
    948
    949	port_tty = kzalloc(sizeof(struct tty_port), GFP_KERNEL);
    950	if (!port_tty)
    951		return -ENOMEM;
    952
    953	port_vcc = vcc_get(tty->index, true);
    954	if (!port_vcc) {
    955		pr_err("VCC: install: Failed to find VCC port\n");
    956		tty->port = NULL;
    957		kfree(port_tty);
    958		return -ENODEV;
    959	}
    960
    961	tty_port_init(port_tty);
    962	port_tty->ops = &vcc_port_ops;
    963	tty->port = port_tty;
    964
    965	port_vcc->tty = tty;
    966
    967	vcc_put(port_vcc, true);
    968
    969	return 0;
    970}
    971
    972static void vcc_cleanup(struct tty_struct *tty)
    973{
    974	struct vcc_port *port;
    975
    976	port = vcc_get(tty->index, true);
    977	if (port) {
    978		port->tty = NULL;
    979
    980		if (port->removed) {
    981			vcc_table_remove(tty->index);
    982			kfree(port->vio.name);
    983			kfree(port->domain);
    984			kfree(port);
    985		} else {
    986			vcc_put(port, true);
    987		}
    988	}
    989
    990	tty_port_destroy(tty->port);
    991	kfree(tty->port);
    992	tty->port = NULL;
    993}
    994
    995static const struct tty_operations vcc_ops = {
    996	.open			= vcc_open,
    997	.close			= vcc_close,
    998	.hangup			= vcc_hangup,
    999	.write			= vcc_write,
   1000	.write_room		= vcc_write_room,
   1001	.chars_in_buffer	= vcc_chars_in_buffer,
   1002	.break_ctl		= vcc_break_ctl,
   1003	.install		= vcc_install,
   1004	.cleanup		= vcc_cleanup,
   1005};
   1006
   1007#define VCC_TTY_FLAGS   (TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_REAL_RAW)
   1008
   1009static int vcc_tty_init(void)
   1010{
   1011	int rv;
   1012
   1013	vcc_tty_driver = tty_alloc_driver(VCC_MAX_PORTS, VCC_TTY_FLAGS);
   1014	if (IS_ERR(vcc_tty_driver)) {
   1015		pr_err("VCC: TTY driver alloc failed\n");
   1016		return PTR_ERR(vcc_tty_driver);
   1017	}
   1018
   1019	vcc_tty_driver->driver_name = "vcc";
   1020	vcc_tty_driver->name = "vcc";
   1021
   1022	vcc_tty_driver->minor_start = VCC_MINOR_START;
   1023	vcc_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM;
   1024	vcc_tty_driver->init_termios = vcc_tty_termios;
   1025
   1026	tty_set_operations(vcc_tty_driver, &vcc_ops);
   1027
   1028	rv = tty_register_driver(vcc_tty_driver);
   1029	if (rv) {
   1030		pr_err("VCC: TTY driver registration failed\n");
   1031		tty_driver_kref_put(vcc_tty_driver);
   1032		vcc_tty_driver = NULL;
   1033		return rv;
   1034	}
   1035
   1036	vccdbg("VCC: TTY driver registered\n");
   1037
   1038	return 0;
   1039}
   1040
   1041static void vcc_tty_exit(void)
   1042{
   1043	tty_unregister_driver(vcc_tty_driver);
   1044	tty_driver_kref_put(vcc_tty_driver);
   1045	vccdbg("VCC: TTY driver unregistered\n");
   1046
   1047	vcc_tty_driver = NULL;
   1048}
   1049
   1050static int __init vcc_init(void)
   1051{
   1052	int rv;
   1053
   1054	rv = vcc_tty_init();
   1055	if (rv) {
   1056		pr_err("VCC: TTY init failed\n");
   1057		return rv;
   1058	}
   1059
   1060	rv = vio_register_driver(&vcc_driver);
   1061	if (rv) {
   1062		pr_err("VCC: VIO driver registration failed\n");
   1063		vcc_tty_exit();
   1064	} else {
   1065		vccdbg("VCC: VIO driver registered successfully\n");
   1066	}
   1067
   1068	return rv;
   1069}
   1070
   1071static void __exit vcc_exit(void)
   1072{
   1073	vio_unregister_driver(&vcc_driver);
   1074	vccdbg("VCC: VIO driver unregistered\n");
   1075	vcc_tty_exit();
   1076	vccdbg("VCC: TTY driver unregistered\n");
   1077}
   1078
   1079module_init(vcc_init);
   1080module_exit(vcc_exit);