linux/arch/um/drivers/line.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
   3 * Licensed under the GPL
   4 */
   5
   6#include "linux/irqreturn.h"
   7#include "linux/kd.h"
   8#include "chan_kern.h"
   9#include "irq_kern.h"
  10#include "irq_user.h"
  11#include "os.h"
  12
  13#define LINE_BUFSIZE 4096
  14
  15static irqreturn_t line_interrupt(int irq, void *data)
  16{
  17        struct chan *chan = data;
  18        struct line *line = chan->line;
  19        struct tty_struct *tty = line->tty;
  20
  21        if (line)
  22                chan_interrupt(&line->chan_list, &line->task, tty, irq);
  23        return IRQ_HANDLED;
  24}
  25
  26static void line_timer_cb(struct work_struct *work)
  27{
  28        struct line *line = container_of(work, struct line, task.work);
  29
  30        if (!line->throttled)
  31                chan_interrupt(&line->chan_list, &line->task, line->tty,
  32                               line->driver->read_irq);
  33}
  34
  35/*
  36 * Returns the free space inside the ring buffer of this line.
  37 *
  38 * Should be called while holding line->lock (this does not modify data).
  39 */
  40static int write_room(struct line *line)
  41{
  42        int n;
  43
  44        if (line->buffer == NULL)
  45                return LINE_BUFSIZE - 1;
  46
  47        /* This is for the case where the buffer is wrapped! */
  48        n = line->head - line->tail;
  49
  50        if (n <= 0)
  51                n = LINE_BUFSIZE + n; /* The other case */
  52        return n - 1;
  53}
  54
  55int line_write_room(struct tty_struct *tty)
  56{
  57        struct line *line = tty->driver_data;
  58        unsigned long flags;
  59        int room;
  60
  61        if (tty->stopped)
  62                return 0;
  63
  64        spin_lock_irqsave(&line->lock, flags);
  65        room = write_room(line);
  66        spin_unlock_irqrestore(&line->lock, flags);
  67
  68        /*XXX: Warning to remove */
  69        if (0 == room)
  70                printk(KERN_DEBUG "%s: %s: no room left in buffer\n",
  71                       __FUNCTION__,tty->name);
  72        return room;
  73}
  74
  75int line_chars_in_buffer(struct tty_struct *tty)
  76{
  77        struct line *line = tty->driver_data;
  78        unsigned long flags;
  79        int ret;
  80
  81        spin_lock_irqsave(&line->lock, flags);
  82
  83        /*write_room subtracts 1 for the needed NULL, so we readd it.*/
  84        ret = LINE_BUFSIZE - (write_room(line) + 1);
  85        spin_unlock_irqrestore(&line->lock, flags);
  86
  87        return ret;
  88}
  89
  90/*
  91 * This copies the content of buf into the circular buffer associated with
  92 * this line.
  93 * The return value is the number of characters actually copied, i.e. the ones
  94 * for which there was space: this function is not supposed to ever flush out
  95 * the circular buffer.
  96 *
  97 * Must be called while holding line->lock!
  98 */
  99static int buffer_data(struct line *line, const char *buf, int len)
 100{
 101        int end, room;
 102
 103        if (line->buffer == NULL) {
 104                line->buffer = kmalloc(LINE_BUFSIZE, GFP_ATOMIC);
 105                if (line->buffer == NULL) {
 106                        printk(KERN_ERR "buffer_data - atomic allocation "
 107                               "failed\n");
 108                        return 0;
 109                }
 110                line->head = line->buffer;
 111                line->tail = line->buffer;
 112        }
 113
 114        room = write_room(line);
 115        len = (len > room) ? room : len;
 116
 117        end = line->buffer + LINE_BUFSIZE - line->tail;
 118
 119        if (len < end) {
 120                memcpy(line->tail, buf, len);
 121                line->tail += len;
 122        }
 123        else {
 124                /* The circular buffer is wrapping */
 125                memcpy(line->tail, buf, end);
 126                buf += end;
 127                memcpy(line->buffer, buf, len - end);
 128                line->tail = line->buffer + len - end;
 129        }
 130
 131        return len;
 132}
 133
 134/*
 135 * Flushes the ring buffer to the output channels. That is, write_chan is
 136 * called, passing it line->head as buffer, and an appropriate count.
 137 *
 138 * On exit, returns 1 when the buffer is empty,
 139 * 0 when the buffer is not empty on exit,
 140 * and -errno when an error occurred.
 141 *
 142 * Must be called while holding line->lock!*/
 143static int flush_buffer(struct line *line)
 144{
 145        int n, count;
 146
 147        if ((line->buffer == NULL) || (line->head == line->tail))
 148                return 1;
 149
 150        if (line->tail < line->head) {
 151                /* line->buffer + LINE_BUFSIZE is the end of the buffer! */
 152                count = line->buffer + LINE_BUFSIZE - line->head;
 153
 154                n = write_chan(&line->chan_list, line->head, count,
 155                               line->driver->write_irq);
 156                if (n < 0)
 157                        return n;
 158                if (n == count) {
 159                        /*
 160                         * We have flushed from ->head to buffer end, now we
 161                         * must flush only from the beginning to ->tail.
 162                         */
 163                        line->head = line->buffer;
 164                } else {
 165                        line->head += n;
 166                        return 0;
 167                }
 168        }
 169
 170        count = line->tail - line->head;
 171        n = write_chan(&line->chan_list, line->head, count,
 172                       line->driver->write_irq);
 173
 174        if (n < 0)
 175                return n;
 176
 177        line->head += n;
 178        return line->head == line->tail;
 179}
 180
 181void line_flush_buffer(struct tty_struct *tty)
 182{
 183        struct line *line = tty->driver_data;
 184        unsigned long flags;
 185        int err;
 186
 187        /*XXX: copied from line_write, verify if it is correct!*/
 188        if (tty->stopped)
 189                return;
 190
 191        spin_lock_irqsave(&line->lock, flags);
 192        err = flush_buffer(line);
 193        spin_unlock_irqrestore(&line->lock, flags);
 194}
 195
 196/*
 197 * We map both ->flush_chars and ->put_char (which go in pair) onto
 198 * ->flush_buffer and ->write. Hope it's not that bad.
 199 */
 200void line_flush_chars(struct tty_struct *tty)
 201{
 202        line_flush_buffer(tty);
 203}
 204
 205void line_put_char(struct tty_struct *tty, unsigned char ch)
 206{
 207        line_write(tty, &ch, sizeof(ch));
 208}
 209
 210int line_write(struct tty_struct *tty, const unsigned char *buf, int len)
 211{
 212        struct line *line = tty->driver_data;
 213        unsigned long flags;
 214        int n, ret = 0;
 215
 216        if (tty->stopped)
 217                return 0;
 218
 219        spin_lock_irqsave(&line->lock, flags);
 220        if (line->head != line->tail)
 221                ret = buffer_data(line, buf, len);
 222        else {
 223                n = write_chan(&line->chan_list, buf, len,
 224                               line->driver->write_irq);
 225                if (n < 0) {
 226                        ret = n;
 227                        goto out_up;
 228                }
 229
 230                len -= n;
 231                ret += n;
 232                if (len > 0)
 233                        ret += buffer_data(line, buf + n, len);
 234        }
 235out_up:
 236        spin_unlock_irqrestore(&line->lock, flags);
 237        return ret;
 238}
 239
 240void line_set_termios(struct tty_struct *tty, struct ktermios * old)
 241{
 242        /* nothing */
 243}
 244
 245static const struct {
 246        int  cmd;
 247        char *level;
 248        char *name;
 249} tty_ioctls[] = {
 250        /* don't print these, they flood the log ... */
 251        { TCGETS,      NULL,       "TCGETS"      },
 252        { TCSETS,      NULL,       "TCSETS"      },
 253        { TCSETSW,     NULL,       "TCSETSW"     },
 254        { TCFLSH,      NULL,       "TCFLSH"      },
 255        { TCSBRK,      NULL,       "TCSBRK"      },
 256
 257        /* general tty stuff */
 258        { TCSETSF,     KERN_DEBUG, "TCSETSF"     },
 259        { TCGETA,      KERN_DEBUG, "TCGETA"      },
 260        { TIOCMGET,    KERN_DEBUG, "TIOCMGET"    },
 261        { TCSBRKP,     KERN_DEBUG, "TCSBRKP"     },
 262        { TIOCMSET,    KERN_DEBUG, "TIOCMSET"    },
 263
 264        /* linux-specific ones */
 265        { TIOCLINUX,   KERN_INFO,  "TIOCLINUX"   },
 266        { KDGKBMODE,   KERN_INFO,  "KDGKBMODE"   },
 267        { KDGKBTYPE,   KERN_INFO,  "KDGKBTYPE"   },
 268        { KDSIGACCEPT, KERN_INFO,  "KDSIGACCEPT" },
 269};
 270
 271int line_ioctl(struct tty_struct *tty, struct file * file,
 272               unsigned int cmd, unsigned long arg)
 273{
 274        int ret;
 275        int i;
 276
 277        ret = 0;
 278        switch(cmd) {
 279#ifdef TIOCGETP
 280        case TIOCGETP:
 281        case TIOCSETP:
 282        case TIOCSETN:
 283#endif
 284#ifdef TIOCGETC
 285        case TIOCGETC:
 286        case TIOCSETC:
 287#endif
 288#ifdef TIOCGLTC
 289        case TIOCGLTC:
 290        case TIOCSLTC:
 291#endif
 292        case TCGETS:
 293        case TCSETSF:
 294        case TCSETSW:
 295        case TCSETS:
 296        case TCGETA:
 297        case TCSETAF:
 298        case TCSETAW:
 299        case TCSETA:
 300        case TCXONC:
 301        case TCFLSH:
 302        case TIOCOUTQ:
 303        case TIOCINQ:
 304        case TIOCGLCKTRMIOS:
 305        case TIOCSLCKTRMIOS:
 306        case TIOCPKT:
 307        case TIOCGSOFTCAR:
 308        case TIOCSSOFTCAR:
 309                return -ENOIOCTLCMD;
 310#if 0
 311        case TCwhatever:
 312                /* do something */
 313                break;
 314#endif
 315        default:
 316                for (i = 0; i < ARRAY_SIZE(tty_ioctls); i++)
 317                        if (cmd == tty_ioctls[i].cmd)
 318                                break;
 319                if (i == ARRAY_SIZE(tty_ioctls)) {
 320                        printk(KERN_ERR "%s: %s: unknown ioctl: 0x%x\n",
 321                               __FUNCTION__, tty->name, cmd);
 322                }
 323                ret = -ENOIOCTLCMD;
 324                break;
 325        }
 326        return ret;
 327}
 328
 329void line_throttle(struct tty_struct *tty)
 330{
 331        struct line *line = tty->driver_data;
 332
 333        deactivate_chan(&line->chan_list, line->driver->read_irq);
 334        line->throttled = 1;
 335}
 336
 337void line_unthrottle(struct tty_struct *tty)
 338{
 339        struct line *line = tty->driver_data;
 340
 341        line->throttled = 0;
 342        chan_interrupt(&line->chan_list, &line->task, tty,
 343                       line->driver->read_irq);
 344
 345        /*
 346         * Maybe there is enough stuff pending that calling the interrupt
 347         * throttles us again.  In this case, line->throttled will be 1
 348         * again and we shouldn't turn the interrupt back on.
 349         */
 350        if (!line->throttled)
 351                reactivate_chan(&line->chan_list, line->driver->read_irq);
 352}
 353
 354static irqreturn_t line_write_interrupt(int irq, void *data)
 355{
 356        struct chan *chan = data;
 357        struct line *line = chan->line;
 358        struct tty_struct *tty = line->tty;
 359        int err;
 360
 361        /*
 362         * Interrupts are disabled here because we registered the interrupt with
 363         * IRQF_DISABLED (see line_setup_irq).
 364         */
 365
 366        spin_lock(&line->lock);
 367        err = flush_buffer(line);
 368        if (err == 0) {
 369                return IRQ_NONE;
 370        } else if (err < 0) {
 371                line->head = line->buffer;
 372                line->tail = line->buffer;
 373        }
 374        spin_unlock(&line->lock);
 375
 376        if (tty == NULL)
 377                return IRQ_NONE;
 378
 379        if (test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags) &&
 380           (tty->ldisc.write_wakeup != NULL))
 381                (tty->ldisc.write_wakeup)(tty);
 382
 383        /*
 384         * BLOCKING mode
 385         * In blocking mode, everything sleeps on tty->write_wait.
 386         * Sleeping in the console driver would break non-blocking
 387         * writes.
 388         */
 389
 390        if (waitqueue_active(&tty->write_wait))
 391                wake_up_interruptible(&tty->write_wait);
 392        return IRQ_HANDLED;
 393}
 394
 395int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
 396{
 397        const struct line_driver *driver = line->driver;
 398        int err = 0, flags = IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM;
 399
 400        if (input)
 401                err = um_request_irq(driver->read_irq, fd, IRQ_READ,
 402                                       line_interrupt, flags,
 403                                       driver->read_irq_name, data);
 404        if (err)
 405                return err;
 406        if (output)
 407                err = um_request_irq(driver->write_irq, fd, IRQ_WRITE,
 408                                        line_write_interrupt, flags,
 409                                        driver->write_irq_name, data);
 410        line->have_irq = 1;
 411        return err;
 412}
 413
 414/*
 415 * Normally, a driver like this can rely mostly on the tty layer
 416 * locking, particularly when it comes to the driver structure.
 417 * However, in this case, mconsole requests can come in "from the
 418 * side", and race with opens and closes.
 419 *
 420 * mconsole config requests will want to be sure the device isn't in
 421 * use, and get_config, open, and close will want a stable
 422 * configuration.  The checking and modification of the configuration
 423 * is done under a spinlock.  Checking whether the device is in use is
 424 * line->tty->count > 1, also under the spinlock.
 425 *
 426 * tty->count serves to decide whether the device should be enabled or
 427 * disabled on the host.  If it's equal to 1, then we are doing the
 428 * first open or last close.  Otherwise, open and close just return.
 429 */
 430
 431int line_open(struct line *lines, struct tty_struct *tty)
 432{
 433        struct line *line = &lines[tty->index];
 434        int err = -ENODEV;
 435
 436        spin_lock(&line->count_lock);
 437        if (!line->valid)
 438                goto out_unlock;
 439
 440        err = 0;
 441        if (tty->count > 1)
 442                goto out_unlock;
 443
 444        spin_unlock(&line->count_lock);
 445
 446        tty->driver_data = line;
 447        line->tty = tty;
 448
 449        err = enable_chan(line);
 450        if (err)
 451                return err;
 452
 453        INIT_DELAYED_WORK(&line->task, line_timer_cb);
 454
 455        if (!line->sigio) {
 456                chan_enable_winch(&line->chan_list, tty);
 457                line->sigio = 1;
 458        }
 459
 460        chan_window_size(&line->chan_list, &tty->winsize.ws_row,
 461                         &tty->winsize.ws_col);
 462
 463        return err;
 464
 465out_unlock:
 466        spin_unlock(&line->count_lock);
 467        return err;
 468}
 469
 470static void unregister_winch(struct tty_struct *tty);
 471
 472void line_close(struct tty_struct *tty, struct file * filp)
 473{
 474        struct line *line = tty->driver_data;
 475
 476        /*
 477         * If line_open fails (and tty->driver_data is never set),
 478         * tty_open will call line_close.  So just return in this case.
 479         */
 480        if (line == NULL)
 481                return;
 482
 483        /* We ignore the error anyway! */
 484        flush_buffer(line);
 485
 486        spin_lock(&line->count_lock);
 487        if (!line->valid)
 488                goto out_unlock;
 489
 490        if (tty->count > 1)
 491                goto out_unlock;
 492
 493        spin_unlock(&line->count_lock);
 494
 495        line->tty = NULL;
 496        tty->driver_data = NULL;
 497
 498        if (line->sigio) {
 499                unregister_winch(tty);
 500                line->sigio = 0;
 501        }
 502
 503        return;
 504
 505out_unlock:
 506        spin_unlock(&line->count_lock);
 507}
 508
 509void close_lines(struct line *lines, int nlines)
 510{
 511        int i;
 512
 513        for(i = 0; i < nlines; i++)
 514                close_chan(&lines[i].chan_list, 0);
 515}
 516
 517static int setup_one_line(struct line *lines, int n, char *init, int init_prio,
 518                          char **error_out)
 519{
 520        struct line *line = &lines[n];
 521        int err = -EINVAL;
 522
 523        spin_lock(&line->count_lock);
 524
 525        if (line->tty != NULL) {
 526                *error_out = "Device is already open";
 527                goto out;
 528        }
 529
 530        if (line->init_pri <= init_prio) {
 531                line->init_pri = init_prio;
 532                if (!strcmp(init, "none"))
 533                        line->valid = 0;
 534                else {
 535                        line->init_str = init;
 536                        line->valid = 1;
 537                }
 538        }
 539        err = 0;
 540out:
 541        spin_unlock(&line->count_lock);
 542        return err;
 543}
 544
 545/*
 546 * Common setup code for both startup command line and mconsole initialization.
 547 * @lines contains the array (of size @num) to modify;
 548 * @init is the setup string;
 549 * @error_out is an error string in the case of failure;
 550 */
 551
 552int line_setup(struct line *lines, unsigned int num, char *init,
 553               char **error_out)
 554{
 555        int i, n, err;
 556        char *end;
 557
 558        if (*init == '=') {
 559                /*
 560                 * We said con=/ssl= instead of con#=, so we are configuring all
 561                 * consoles at once.
 562                 */
 563                n = -1;
 564        }
 565        else {
 566                n = simple_strtoul(init, &end, 0);
 567                if (*end != '=') {
 568                        *error_out = "Couldn't parse device number";
 569                        return -EINVAL;
 570                }
 571                init = end;
 572        }
 573        init++;
 574
 575        if (n >= (signed int) num) {
 576                *error_out = "Device number out of range";
 577                return -EINVAL;
 578        }
 579        else if (n >= 0) {
 580                err = setup_one_line(lines, n, init, INIT_ONE, error_out);
 581                if (err)
 582                        return err;
 583        }
 584        else {
 585                for(i = 0; i < num; i++) {
 586                        err = setup_one_line(lines, i, init, INIT_ALL,
 587                                             error_out);
 588                        if (err)
 589                                return err;
 590                }
 591        }
 592        return n == -1 ? num : n;
 593}
 594
 595int line_config(struct line *lines, unsigned int num, char *str,
 596                const struct chan_opts *opts, char **error_out)
 597{
 598        struct line *line;
 599        char *new;
 600        int n;
 601
 602        if (*str == '=') {
 603                *error_out = "Can't configure all devices from mconsole";
 604                return -EINVAL;
 605        }
 606
 607        new = kstrdup(str, GFP_KERNEL);
 608        if (new == NULL) {
 609                *error_out = "Failed to allocate memory";
 610                return -ENOMEM;
 611        }
 612        n = line_setup(lines, num, new, error_out);
 613        if (n < 0)
 614                return n;
 615
 616        line = &lines[n];
 617        return parse_chan_pair(line->init_str, line, n, opts, error_out);
 618}
 619
 620int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
 621                    int size, char **error_out)
 622{
 623        struct line *line;
 624        char *end;
 625        int dev, n = 0;
 626
 627        dev = simple_strtoul(name, &end, 0);
 628        if ((*end != '\0') || (end == name)) {
 629                *error_out = "line_get_config failed to parse device number";
 630                return 0;
 631        }
 632
 633        if ((dev < 0) || (dev >= num)) {
 634                *error_out = "device number out of range";
 635                return 0;
 636        }
 637
 638        line = &lines[dev];
 639
 640        spin_lock(&line->count_lock);
 641        if (!line->valid)
 642                CONFIG_CHUNK(str, size, n, "none", 1);
 643        else if (line->tty == NULL)
 644                CONFIG_CHUNK(str, size, n, line->init_str, 1);
 645        else n = chan_config_string(&line->chan_list, str, size, error_out);
 646        spin_unlock(&line->count_lock);
 647
 648        return n;
 649}
 650
 651int line_id(char **str, int *start_out, int *end_out)
 652{
 653        char *end;
 654        int n;
 655
 656        n = simple_strtoul(*str, &end, 0);
 657        if ((*end != '\0') || (end == *str))
 658                return -1;
 659
 660        *str = end;
 661        *start_out = n;
 662        *end_out = n;
 663        return n;
 664}
 665
 666int line_remove(struct line *lines, unsigned int num, int n, char **error_out)
 667{
 668        int err;
 669        char config[sizeof("conxxxx=none\0")];
 670
 671        sprintf(config, "%d=none", n);
 672        err = line_setup(lines, num, config, error_out);
 673        if (err >= 0)
 674                err = 0;
 675        return err;
 676}
 677
 678struct tty_driver *register_lines(struct line_driver *line_driver,
 679                                  const struct tty_operations *ops,
 680                                  struct line *lines, int nlines)
 681{
 682        int i;
 683        struct tty_driver *driver = alloc_tty_driver(nlines);
 684
 685        if (!driver)
 686                return NULL;
 687
 688        driver->driver_name = line_driver->name;
 689        driver->name = line_driver->device_name;
 690        driver->major = line_driver->major;
 691        driver->minor_start = line_driver->minor_start;
 692        driver->type = line_driver->type;
 693        driver->subtype = line_driver->subtype;
 694        driver->flags = TTY_DRIVER_REAL_RAW;
 695        driver->init_termios = tty_std_termios;
 696        tty_set_operations(driver, ops);
 697
 698        if (tty_register_driver(driver)) {
 699                printk(KERN_ERR "register_lines : can't register %s driver\n",
 700                       line_driver->name);
 701                put_tty_driver(driver);
 702                return NULL;
 703        }
 704
 705        for(i = 0; i < nlines; i++) {
 706                if (!lines[i].valid)
 707                        tty_unregister_device(driver, i);
 708        }
 709
 710        mconsole_register_dev(&line_driver->mc);
 711        return driver;
 712}
 713
 714static DEFINE_SPINLOCK(winch_handler_lock);
 715static LIST_HEAD(winch_handlers);
 716
 717void lines_init(struct line *lines, int nlines, struct chan_opts *opts)
 718{
 719        struct line *line;
 720        char *error;
 721        int i;
 722
 723        for(i = 0; i < nlines; i++) {
 724                line = &lines[i];
 725                INIT_LIST_HEAD(&line->chan_list);
 726
 727                if (line->init_str == NULL)
 728                        continue;
 729
 730                line->init_str = kstrdup(line->init_str, GFP_KERNEL);
 731                if (line->init_str == NULL)
 732                        printk(KERN_ERR "lines_init - kstrdup returned NULL\n");
 733
 734                if (parse_chan_pair(line->init_str, line, i, opts, &error)) {
 735                        printk(KERN_ERR "parse_chan_pair failed for "
 736                               "device %d : %s\n", i, error);
 737                        line->valid = 0;
 738                }
 739        }
 740}
 741
 742struct winch {
 743        struct list_head list;
 744        int fd;
 745        int tty_fd;
 746        int pid;
 747        struct tty_struct *tty;
 748        unsigned long stack;
 749};
 750
 751static void free_winch(struct winch *winch, int free_irq_ok)
 752{
 753        list_del(&winch->list);
 754
 755        if (winch->pid != -1)
 756                os_kill_process(winch->pid, 1);
 757        if (winch->fd != -1)
 758                os_close_file(winch->fd);
 759        if (winch->stack != 0)
 760                free_stack(winch->stack, 0);
 761        if (free_irq_ok)
 762                free_irq(WINCH_IRQ, winch);
 763        kfree(winch);
 764}
 765
 766static irqreturn_t winch_interrupt(int irq, void *data)
 767{
 768        struct winch *winch = data;
 769        struct tty_struct *tty;
 770        struct line *line;
 771        int err;
 772        char c;
 773
 774        if (winch->fd != -1) {
 775                err = generic_read(winch->fd, &c, NULL);
 776                if (err < 0) {
 777                        if (err != -EAGAIN) {
 778                                printk(KERN_ERR "winch_interrupt : "
 779                                       "read failed, errno = %d\n", -err);
 780                                printk(KERN_ERR "fd %d is losing SIGWINCH "
 781                                       "support\n", winch->tty_fd);
 782                                free_winch(winch, 0);
 783                                return IRQ_HANDLED;
 784                        }
 785                        goto out;
 786                }
 787        }
 788        tty = winch->tty;
 789        if (tty != NULL) {
 790                line = tty->driver_data;
 791                chan_window_size(&line->chan_list, &tty->winsize.ws_row,
 792                                 &tty->winsize.ws_col);
 793                kill_pgrp(tty->pgrp, SIGWINCH, 1);
 794        }
 795 out:
 796        if (winch->fd != -1)
 797                reactivate_fd(winch->fd, WINCH_IRQ);
 798        return IRQ_HANDLED;
 799}
 800
 801void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty,
 802                        unsigned long stack)
 803{
 804        struct winch *winch;
 805
 806        winch = kmalloc(sizeof(*winch), GFP_KERNEL);
 807        if (winch == NULL) {
 808                printk(KERN_ERR "register_winch_irq - kmalloc failed\n");
 809                goto cleanup;
 810        }
 811
 812        *winch = ((struct winch) { .list        = LIST_HEAD_INIT(winch->list),
 813                                   .fd          = fd,
 814                                   .tty_fd      = tty_fd,
 815                                   .pid         = pid,
 816                                   .tty         = tty,
 817                                   .stack       = stack });
 818
 819        if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
 820                           IRQF_DISABLED | IRQF_SHARED | IRQF_SAMPLE_RANDOM,
 821                           "winch", winch) < 0) {
 822                printk(KERN_ERR "register_winch_irq - failed to register "
 823                       "IRQ\n");
 824                goto out_free;
 825        }
 826
 827        spin_lock(&winch_handler_lock);
 828        list_add(&winch->list, &winch_handlers);
 829        spin_unlock(&winch_handler_lock);
 830
 831        return;
 832
 833 out_free:
 834        kfree(winch);
 835 cleanup:
 836        os_kill_process(pid, 1);
 837        os_close_file(fd);
 838        if (stack != 0)
 839                free_stack(stack, 0);
 840}
 841
 842static void unregister_winch(struct tty_struct *tty)
 843{
 844        struct list_head *ele;
 845        struct winch *winch;
 846
 847        spin_lock(&winch_handler_lock);
 848
 849        list_for_each(ele, &winch_handlers) {
 850                winch = list_entry(ele, struct winch, list);
 851                if (winch->tty == tty) {
 852                        free_winch(winch, 1);
 853                        break;
 854                }
 855        }
 856        spin_unlock(&winch_handler_lock);
 857}
 858
 859static void winch_cleanup(void)
 860{
 861        struct list_head *ele, *next;
 862        struct winch *winch;
 863
 864        spin_lock(&winch_handler_lock);
 865
 866        list_for_each_safe(ele, next, &winch_handlers) {
 867                winch = list_entry(ele, struct winch, list);
 868                free_winch(winch, 1);
 869        }
 870
 871        spin_unlock(&winch_handler_lock);
 872}
 873__uml_exitcall(winch_cleanup);
 874
 875char *add_xterm_umid(char *base)
 876{
 877        char *umid, *title;
 878        int len;
 879
 880        umid = get_umid();
 881        if (*umid == '\0')
 882                return base;
 883
 884        len = strlen(base) + strlen(" ()") + strlen(umid) + 1;
 885        title = kmalloc(len, GFP_KERNEL);
 886        if (title == NULL) {
 887                printk(KERN_ERR "Failed to allocate buffer for xterm title\n");
 888                return base;
 889        }
 890
 891        snprintf(title, len, "%s (%s)", base, umid);
 892        return title;
 893}
 894