linux/drivers/tty/metag_da.c
<<
>>
Prefs
   1/*
   2 *  dashtty.c - tty driver for Dash channels interface.
   3 *
   4 *  Copyright (C) 2007,2008,2012 Imagination Technologies
   5 *
   6 * This file is subject to the terms and conditions of the GNU General Public
   7 * License.  See the file COPYING in the main directory of this archive
   8 * for more details.
   9 *
  10 */
  11
  12#include <linux/atomic.h>
  13#include <linux/completion.h>
  14#include <linux/console.h>
  15#include <linux/delay.h>
  16#include <linux/export.h>
  17#include <linux/init.h>
  18#include <linux/kernel.h>
  19#include <linux/kthread.h>
  20#include <linux/mutex.h>
  21#include <linux/sched.h>
  22#include <linux/serial.h>
  23#include <linux/slab.h>
  24#include <linux/spinlock.h>
  25#include <linux/string.h>
  26#include <linux/timer.h>
  27#include <linux/tty.h>
  28#include <linux/tty_driver.h>
  29#include <linux/tty_flip.h>
  30#include <linux/uaccess.h>
  31
  32#include <asm/da.h>
  33
  34/* Channel error codes */
  35#define CONAOK  0
  36#define CONERR  1
  37#define CONBAD  2
  38#define CONPRM  3
  39#define CONADR  4
  40#define CONCNT  5
  41#define CONCBF  6
  42#define CONCBE  7
  43#define CONBSY  8
  44
  45/* Default channel for the console */
  46#define CONSOLE_CHANNEL      1
  47
  48#define NUM_TTY_CHANNELS     6
  49
  50/* Auto allocate */
  51#define DA_TTY_MAJOR        0
  52
  53/* A speedy poll rate helps the userland debug process connection response.
  54 * But, if you set it too high then no other userland processes get much
  55 * of a look in.
  56 */
  57#define DA_TTY_POLL (HZ / 50)
  58
  59/*
  60 * A short put delay improves latency but has a high throughput overhead
  61 */
  62#define DA_TTY_PUT_DELAY (HZ / 100)
  63
  64static atomic_t num_channels_need_poll = ATOMIC_INIT(0);
  65
  66static struct timer_list poll_timer;
  67
  68static struct tty_driver *channel_driver;
  69
  70static struct timer_list put_timer;
  71static struct task_struct *dashtty_thread;
  72
  73#define RX_BUF_SIZE 1024
  74
  75enum {
  76        INCHR = 1,
  77        OUTCHR,
  78        RDBUF,
  79        WRBUF,
  80        RDSTAT
  81};
  82
  83/**
  84 * struct dashtty_port - Wrapper struct for dashtty tty_port.
  85 * @port:               TTY port data
  86 * @rx_lock:            Lock for rx_buf.
  87 *                      This protects between the poll timer and user context.
  88 *                      It's also held during read SWITCH operations.
  89 * @rx_buf:             Read buffer
  90 * @xmit_lock:          Lock for xmit_*, and port.xmit_buf.
  91 *                      This protects between user context and kernel thread.
  92 *                      It's also held during write SWITCH operations.
  93 * @xmit_cnt:           Size of xmit buffer contents
  94 * @xmit_head:          Head of xmit buffer where data is written
  95 * @xmit_tail:          Tail of xmit buffer where data is read
  96 * @xmit_empty:         Completion for xmit buffer being empty
  97 */
  98struct dashtty_port {
  99        struct tty_port          port;
 100        spinlock_t               rx_lock;
 101        void                    *rx_buf;
 102        struct mutex             xmit_lock;
 103        unsigned int             xmit_cnt;
 104        unsigned int             xmit_head;
 105        unsigned int             xmit_tail;
 106        struct completion        xmit_empty;
 107};
 108
 109static struct dashtty_port dashtty_ports[NUM_TTY_CHANNELS];
 110
 111static atomic_t dashtty_xmit_cnt = ATOMIC_INIT(0);
 112static wait_queue_head_t dashtty_waitqueue;
 113
 114/*
 115 * Low-level DA channel access routines
 116 */
 117static int chancall(int in_bios_function, int in_channel,
 118                    int in_arg2, void *in_arg3,
 119                    void *in_arg4)
 120{
 121        register int   bios_function asm("D1Ar1") = in_bios_function;
 122        register int   channel       asm("D0Ar2") = in_channel;
 123        register int   arg2          asm("D1Ar3") = in_arg2;
 124        register void *arg3          asm("D0Ar4") = in_arg3;
 125        register void *arg4          asm("D1Ar5") = in_arg4;
 126        register int   bios_call     asm("D0Ar6") = 3;
 127        register int   result        asm("D0Re0");
 128
 129        asm volatile (
 130                "MSETL  [A0StP++], %6,%4,%2\n\t"
 131                "ADD    A0StP, A0StP, #8\n\t"
 132                "SWITCH #0x0C30208\n\t"
 133                "GETD   %0, [A0StP+#-8]\n\t"
 134                "SUB    A0StP, A0StP, #(4*6)+8\n\t"
 135                : "=d" (result)   /* outs */
 136                : "d" (bios_function),
 137                  "d" (channel),
 138                  "d" (arg2),
 139                  "d" (arg3),
 140                  "d" (arg4),
 141                  "d" (bios_call) /* ins */
 142                : "memory");
 143
 144        return result;
 145}
 146
 147/*
 148 * Attempts to fetch count bytes from channel and returns actual count.
 149 */
 150static int fetch_data(unsigned int channel)
 151{
 152        struct dashtty_port *dport = &dashtty_ports[channel];
 153        int received = 0;
 154
 155        spin_lock_bh(&dport->rx_lock);
 156        /* check the port isn't being shut down */
 157        if (!dport->rx_buf)
 158                goto unlock;
 159        if (chancall(RDBUF, channel, RX_BUF_SIZE,
 160                     (void *)dport->rx_buf, &received) == CONAOK) {
 161                if (received) {
 162                        int space;
 163                        unsigned char *cbuf;
 164
 165                        space = tty_prepare_flip_string(&dport->port, &cbuf,
 166                                                        received);
 167
 168                        if (space <= 0)
 169                                goto unlock;
 170
 171                        memcpy(cbuf, dport->rx_buf, space);
 172                        tty_flip_buffer_push(&dport->port);
 173                }
 174        }
 175unlock:
 176        spin_unlock_bh(&dport->rx_lock);
 177
 178        return received;
 179}
 180
 181/**
 182 * find_channel_to_poll() - Returns number of the next channel to poll.
 183 * Returns:     The number of the next channel to poll, or -1 if none need
 184 *              polling.
 185 */
 186static int find_channel_to_poll(void)
 187{
 188        static int last_polled_channel;
 189        int last = last_polled_channel;
 190        int chan;
 191        struct dashtty_port *dport;
 192
 193        for (chan = last + 1; ; ++chan) {
 194                if (chan >= NUM_TTY_CHANNELS)
 195                        chan = 0;
 196
 197                dport = &dashtty_ports[chan];
 198                if (dport->rx_buf) {
 199                        last_polled_channel = chan;
 200                        return chan;
 201                }
 202
 203                if (chan == last)
 204                        break;
 205        }
 206        return -1;
 207}
 208
 209/**
 210 * put_channel_data() - Write out a block of channel data.
 211 * @chan:       DA channel number.
 212 *
 213 * Write a single block of data out to the debug adapter. If the circular buffer
 214 * is wrapped then only the first block is written.
 215 *
 216 * Returns:     1 if the remote buffer was too full to accept data.
 217 *              0 otherwise.
 218 */
 219static int put_channel_data(unsigned int chan)
 220{
 221        struct dashtty_port *dport;
 222        struct tty_struct *tty;
 223        int number_written;
 224        unsigned int count = 0;
 225
 226        dport = &dashtty_ports[chan];
 227        mutex_lock(&dport->xmit_lock);
 228        if (dport->xmit_cnt) {
 229                count = min((unsigned int)(SERIAL_XMIT_SIZE - dport->xmit_tail),
 230                            dport->xmit_cnt);
 231                chancall(WRBUF, chan, count,
 232                         dport->port.xmit_buf + dport->xmit_tail,
 233                         &number_written);
 234                dport->xmit_cnt -= number_written;
 235                if (!dport->xmit_cnt) {
 236                        /* reset pointers to avoid wraps */
 237                        dport->xmit_head = 0;
 238                        dport->xmit_tail = 0;
 239                        complete(&dport->xmit_empty);
 240                } else {
 241                        dport->xmit_tail += number_written;
 242                        if (dport->xmit_tail >= SERIAL_XMIT_SIZE)
 243                                dport->xmit_tail -= SERIAL_XMIT_SIZE;
 244                }
 245                atomic_sub(number_written, &dashtty_xmit_cnt);
 246        }
 247        mutex_unlock(&dport->xmit_lock);
 248
 249        /* if we've made more data available, wake up tty */
 250        if (count && number_written) {
 251                tty = tty_port_tty_get(&dport->port);
 252                if (tty) {
 253                        tty_wakeup(tty);
 254                        tty_kref_put(tty);
 255                }
 256        }
 257
 258        /* did the write fail? */
 259        return count && !number_written;
 260}
 261
 262/**
 263 * put_data() - Kernel thread to write out blocks of channel data to DA.
 264 * @arg:        Unused.
 265 *
 266 * This kernel thread runs while @dashtty_xmit_cnt != 0, and loops over the
 267 * channels to write out any buffered data. If any of the channels stall due to
 268 * the remote buffer being full, a hold off happens to allow the debugger to
 269 * drain the buffer.
 270 */
 271static int put_data(void *arg)
 272{
 273        unsigned int chan, stall;
 274
 275        __set_current_state(TASK_RUNNING);
 276        while (!kthread_should_stop()) {
 277                /*
 278                 * For each channel see if there's anything to transmit in the
 279                 * port's xmit_buf.
 280                 */
 281                stall = 0;
 282                for (chan = 0; chan < NUM_TTY_CHANNELS; ++chan)
 283                        stall += put_channel_data(chan);
 284
 285                /*
 286                 * If some of the buffers are full, hold off for a short while
 287                 * to allow them to empty.
 288                 */
 289                if (stall)
 290                        msleep(25);
 291
 292                wait_event_interruptible(dashtty_waitqueue,
 293                                         atomic_read(&dashtty_xmit_cnt));
 294        }
 295
 296        return 0;
 297}
 298
 299/*
 300 *      This gets called every DA_TTY_POLL and polls the channels for data
 301 */
 302static void dashtty_timer(unsigned long ignored)
 303{
 304        int channel;
 305
 306        /* If there are no ports open do nothing and don't poll again. */
 307        if (!atomic_read(&num_channels_need_poll))
 308                return;
 309
 310        channel = find_channel_to_poll();
 311
 312        /* Did we find a channel to poll? */
 313        if (channel >= 0)
 314                fetch_data(channel);
 315
 316        mod_timer_pinned(&poll_timer, jiffies + DA_TTY_POLL);
 317}
 318
 319static void add_poll_timer(struct timer_list *poll_timer)
 320{
 321        setup_timer(poll_timer, dashtty_timer, 0);
 322        poll_timer->expires = jiffies + DA_TTY_POLL;
 323
 324        /*
 325         * Always attach the timer to the boot CPU. The DA channels are per-CPU
 326         * so all polling should be from a single CPU.
 327         */
 328        add_timer_on(poll_timer, 0);
 329}
 330
 331static int dashtty_port_activate(struct tty_port *port, struct tty_struct *tty)
 332{
 333        struct dashtty_port *dport = container_of(port, struct dashtty_port,
 334                                                  port);
 335        void *rx_buf;
 336
 337        /* Allocate the buffer we use for writing data */
 338        if (tty_port_alloc_xmit_buf(port) < 0)
 339                goto err;
 340
 341        /* Allocate the buffer we use for reading data */
 342        rx_buf = kzalloc(RX_BUF_SIZE, GFP_KERNEL);
 343        if (!rx_buf)
 344                goto err_free_xmit;
 345
 346        spin_lock_bh(&dport->rx_lock);
 347        dport->rx_buf = rx_buf;
 348        spin_unlock_bh(&dport->rx_lock);
 349
 350        /*
 351         * Don't add the poll timer if we're opening a console. This
 352         * avoids the overhead of polling the Dash but means it is not
 353         * possible to have a login on /dev/console.
 354         *
 355         */
 356        if (dport != &dashtty_ports[CONSOLE_CHANNEL])
 357                if (atomic_inc_return(&num_channels_need_poll) == 1)
 358                        add_poll_timer(&poll_timer);
 359
 360        return 0;
 361err_free_xmit:
 362        tty_port_free_xmit_buf(port);
 363err:
 364        return -ENOMEM;
 365}
 366
 367static void dashtty_port_shutdown(struct tty_port *port)
 368{
 369        struct dashtty_port *dport = container_of(port, struct dashtty_port,
 370                                                  port);
 371        void *rx_buf;
 372        unsigned int count;
 373
 374        /* stop reading */
 375        if (dport != &dashtty_ports[CONSOLE_CHANNEL])
 376                if (atomic_dec_and_test(&num_channels_need_poll))
 377                        del_timer_sync(&poll_timer);
 378
 379        mutex_lock(&dport->xmit_lock);
 380        count = dport->xmit_cnt;
 381        mutex_unlock(&dport->xmit_lock);
 382        if (count) {
 383                /*
 384                 * There's still data to write out, so wake and wait for the
 385                 * writer thread to drain the buffer.
 386                 */
 387                del_timer(&put_timer);
 388                wake_up_interruptible(&dashtty_waitqueue);
 389                wait_for_completion(&dport->xmit_empty);
 390        }
 391
 392        /* Null the read buffer (timer could still be running!) */
 393        spin_lock_bh(&dport->rx_lock);
 394        rx_buf = dport->rx_buf;
 395        dport->rx_buf = NULL;
 396        spin_unlock_bh(&dport->rx_lock);
 397        /* Free the read buffer */
 398        kfree(rx_buf);
 399
 400        /* Free the write buffer */
 401        tty_port_free_xmit_buf(port);
 402}
 403
 404static const struct tty_port_operations dashtty_port_ops = {
 405        .activate       = dashtty_port_activate,
 406        .shutdown       = dashtty_port_shutdown,
 407};
 408
 409static int dashtty_install(struct tty_driver *driver, struct tty_struct *tty)
 410{
 411        return tty_port_install(&dashtty_ports[tty->index].port, driver, tty);
 412}
 413
 414static int dashtty_open(struct tty_struct *tty, struct file *filp)
 415{
 416        return tty_port_open(tty->port, tty, filp);
 417}
 418
 419static void dashtty_close(struct tty_struct *tty, struct file *filp)
 420{
 421        return tty_port_close(tty->port, tty, filp);
 422}
 423
 424static void dashtty_hangup(struct tty_struct *tty)
 425{
 426        int channel;
 427        struct dashtty_port *dport;
 428
 429        channel = tty->index;
 430        dport = &dashtty_ports[channel];
 431
 432        /* drop any data in the xmit buffer */
 433        mutex_lock(&dport->xmit_lock);
 434        if (dport->xmit_cnt) {
 435                atomic_sub(dport->xmit_cnt, &dashtty_xmit_cnt);
 436                dport->xmit_cnt = 0;
 437                dport->xmit_head = 0;
 438                dport->xmit_tail = 0;
 439                complete(&dport->xmit_empty);
 440        }
 441        mutex_unlock(&dport->xmit_lock);
 442
 443        tty_port_hangup(tty->port);
 444}
 445
 446/**
 447 * dashtty_put_timer() - Delayed wake up of kernel thread.
 448 * @ignored:    unused
 449 *
 450 * This timer function wakes up the kernel thread if any data exists in the
 451 * buffers. It is used to delay the expensive writeout until the writer has
 452 * stopped writing.
 453 */
 454static void dashtty_put_timer(unsigned long ignored)
 455{
 456        if (atomic_read(&dashtty_xmit_cnt))
 457                wake_up_interruptible(&dashtty_waitqueue);
 458}
 459
 460static int dashtty_write(struct tty_struct *tty, const unsigned char *buf,
 461                         int total)
 462{
 463        int channel, count, block;
 464        struct dashtty_port *dport;
 465
 466        /* Determine the channel */
 467        channel = tty->index;
 468        dport = &dashtty_ports[channel];
 469
 470        /*
 471         * Write to output buffer.
 472         *
 473         * The reason that we asynchronously write the buffer is because if we
 474         * were to write the buffer synchronously then because DA channels are
 475         * per-CPU the buffer would be written to the channel of whatever CPU
 476         * we're running on.
 477         *
 478         * What we actually want to happen is have all input and output done on
 479         * one CPU.
 480         */
 481        mutex_lock(&dport->xmit_lock);
 482        /* work out how many bytes we can write to the xmit buffer */
 483        total = min(total, (int)(SERIAL_XMIT_SIZE - dport->xmit_cnt));
 484        atomic_add(total, &dashtty_xmit_cnt);
 485        dport->xmit_cnt += total;
 486        /* write the actual bytes (may need splitting if it wraps) */
 487        for (count = total; count; count -= block) {
 488                block = min(count, (int)(SERIAL_XMIT_SIZE - dport->xmit_head));
 489                memcpy(dport->port.xmit_buf + dport->xmit_head, buf, block);
 490                dport->xmit_head += block;
 491                if (dport->xmit_head >= SERIAL_XMIT_SIZE)
 492                        dport->xmit_head -= SERIAL_XMIT_SIZE;
 493                buf += block;
 494        }
 495        count = dport->xmit_cnt;
 496        /* xmit buffer no longer empty? */
 497        if (count)
 498                INIT_COMPLETION(dport->xmit_empty);
 499        mutex_unlock(&dport->xmit_lock);
 500
 501        if (total) {
 502                /*
 503                 * If the buffer is full, wake up the kthread, otherwise allow
 504                 * some more time for the buffer to fill up a bit before waking
 505                 * it.
 506                 */
 507                if (count == SERIAL_XMIT_SIZE) {
 508                        del_timer(&put_timer);
 509                        wake_up_interruptible(&dashtty_waitqueue);
 510                } else {
 511                        mod_timer(&put_timer, jiffies + DA_TTY_PUT_DELAY);
 512                }
 513        }
 514        return total;
 515}
 516
 517static int dashtty_write_room(struct tty_struct *tty)
 518{
 519        struct dashtty_port *dport;
 520        int channel;
 521        int room;
 522
 523        channel = tty->index;
 524        dport = &dashtty_ports[channel];
 525
 526        /* report the space in the xmit buffer */
 527        mutex_lock(&dport->xmit_lock);
 528        room = SERIAL_XMIT_SIZE - dport->xmit_cnt;
 529        mutex_unlock(&dport->xmit_lock);
 530
 531        return room;
 532}
 533
 534static int dashtty_chars_in_buffer(struct tty_struct *tty)
 535{
 536        struct dashtty_port *dport;
 537        int channel;
 538        int chars;
 539
 540        channel = tty->index;
 541        dport = &dashtty_ports[channel];
 542
 543        /* report the number of bytes in the xmit buffer */
 544        mutex_lock(&dport->xmit_lock);
 545        chars = dport->xmit_cnt;
 546        mutex_unlock(&dport->xmit_lock);
 547
 548        return chars;
 549}
 550
 551static const struct tty_operations dashtty_ops = {
 552        .install                = dashtty_install,
 553        .open                   = dashtty_open,
 554        .close                  = dashtty_close,
 555        .hangup                 = dashtty_hangup,
 556        .write                  = dashtty_write,
 557        .write_room             = dashtty_write_room,
 558        .chars_in_buffer        = dashtty_chars_in_buffer,
 559};
 560
 561static int __init dashtty_init(void)
 562{
 563        int ret;
 564        int nport;
 565        struct dashtty_port *dport;
 566
 567        if (!metag_da_enabled())
 568                return -ENODEV;
 569
 570        channel_driver = tty_alloc_driver(NUM_TTY_CHANNELS,
 571                                          TTY_DRIVER_REAL_RAW);
 572        if (IS_ERR(channel_driver))
 573                return PTR_ERR(channel_driver);
 574
 575        channel_driver->driver_name = "metag_da";
 576        channel_driver->name = "ttyDA";
 577        channel_driver->major = DA_TTY_MAJOR;
 578        channel_driver->minor_start = 0;
 579        channel_driver->type = TTY_DRIVER_TYPE_SERIAL;
 580        channel_driver->subtype = SERIAL_TYPE_NORMAL;
 581        channel_driver->init_termios = tty_std_termios;
 582        channel_driver->init_termios.c_cflag |= CLOCAL;
 583
 584        tty_set_operations(channel_driver, &dashtty_ops);
 585        for (nport = 0; nport < NUM_TTY_CHANNELS; nport++) {
 586                dport = &dashtty_ports[nport];
 587                tty_port_init(&dport->port);
 588                dport->port.ops = &dashtty_port_ops;
 589                spin_lock_init(&dport->rx_lock);
 590                mutex_init(&dport->xmit_lock);
 591                /* the xmit buffer starts empty, i.e. completely written */
 592                init_completion(&dport->xmit_empty);
 593                complete(&dport->xmit_empty);
 594        }
 595
 596        setup_timer(&put_timer, dashtty_put_timer, 0);
 597
 598        init_waitqueue_head(&dashtty_waitqueue);
 599        dashtty_thread = kthread_create(put_data, NULL, "ttyDA");
 600        if (IS_ERR(dashtty_thread)) {
 601                pr_err("Couldn't create dashtty thread\n");
 602                ret = PTR_ERR(dashtty_thread);
 603                goto err_destroy_ports;
 604        }
 605        /*
 606         * Bind the writer thread to the boot CPU so it can't migrate.
 607         * DA channels are per-CPU and we want all channel I/O to be on a single
 608         * predictable CPU.
 609         */
 610        kthread_bind(dashtty_thread, 0);
 611        wake_up_process(dashtty_thread);
 612
 613        ret = tty_register_driver(channel_driver);
 614
 615        if (ret < 0) {
 616                pr_err("Couldn't install dashtty driver: err %d\n",
 617                       ret);
 618                goto err_stop_kthread;
 619        }
 620
 621        return 0;
 622
 623err_stop_kthread:
 624        kthread_stop(dashtty_thread);
 625err_destroy_ports:
 626        for (nport = 0; nport < NUM_TTY_CHANNELS; nport++) {
 627                dport = &dashtty_ports[nport];
 628                tty_port_destroy(&dport->port);
 629        }
 630        put_tty_driver(channel_driver);
 631        return ret;
 632}
 633
 634static void dashtty_exit(void)
 635{
 636        int nport;
 637        struct dashtty_port *dport;
 638
 639        del_timer_sync(&put_timer);
 640        kthread_stop(dashtty_thread);
 641        del_timer_sync(&poll_timer);
 642        tty_unregister_driver(channel_driver);
 643        for (nport = 0; nport < NUM_TTY_CHANNELS; nport++) {
 644                dport = &dashtty_ports[nport];
 645                tty_port_destroy(&dport->port);
 646        }
 647        put_tty_driver(channel_driver);
 648}
 649
 650module_init(dashtty_init);
 651module_exit(dashtty_exit);
 652
 653#ifdef CONFIG_DA_CONSOLE
 654
 655static void dash_console_write(struct console *co, const char *s,
 656                               unsigned int count)
 657{
 658        int actually_written;
 659
 660        chancall(WRBUF, CONSOLE_CHANNEL, count, (void *)s, &actually_written);
 661}
 662
 663static struct tty_driver *dash_console_device(struct console *c, int *index)
 664{
 665        *index = c->index;
 666        return channel_driver;
 667}
 668
 669struct console dash_console = {
 670        .name = "ttyDA",
 671        .write = dash_console_write,
 672        .device = dash_console_device,
 673        .flags = CON_PRINTBUFFER,
 674        .index = 1,
 675};
 676
 677#endif
 678
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.