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