CTC++ Coverage Report - Execution Profile    #540/1532

Files Summary | Functions Summary | Execution Profile | Index | No Index
First | Previous | Next | Last


File: drivers/net/ppp_async.c
Instrumentation mode: function-decision-multicondition
TER: 0 % ( 0/540)

Start/ End/    
True False - Line Source

  1 /*
  2  * PPP async serial channel driver for Linux.
  3  *
  4  * Copyright 1999 Paul Mackerras.
  5  *
  6  *  This program is free software; you can redistribute it and/or
  7  *  modify it under the terms of the GNU General Public License
  8  *  as published by the Free Software Foundation; either version
  9  *  2 of the License, or (at your option) any later version.
  10  *
  11  * This driver provides the encapsulation and framing for sending
  12  * and receiving PPP frames over async serial lines.  It relies on
  13  * the generic PPP layer to give it frames to send and to process
  14  * received frames.  It implements the PPP line discipline.
  15  *
  16  * Part of the code in this driver was inspired by the old async-only
  17  * PPP driver, written by Michael Callahan and Al Longyear, and
  18  * subsequently hacked by Paul Mackerras.
  19  */
  20 
  21 #include <linux/module.h>
  22 #include <linux/kernel.h>
  23 #include <linux/skbuff.h>
  24 #include <linux/tty.h>
  25 #include <linux/netdevice.h>
  26 #include <linux/poll.h>
  27 #include <linux/crc-ccitt.h>
  28 #include <linux/ppp_defs.h>
  29 #include <linux/if_ppp.h>
  30 #include <linux/ppp_channel.h>
  31 #include <linux/spinlock.h>
  32 #include <linux/init.h>
  33 #include <asm/uaccess.h>
  34 #include <asm/string.h>
  35 
  36 #define PPP_VERSION   "2.4.2"
  37 
  38 #define OBUFSIZE   256
  39 
  40 /* Structure for storing local state. */
  41 struct asyncppp {
  42    struct tty_struct *tty;
  43    unsigned int   flags;
  44    unsigned int   state;
  45    unsigned int   rbits;
  46    int      mru;
  47    spinlock_t   xmit_lock;
  48    spinlock_t   recv_lock;
  49    unsigned long   xmit_flags;
  50    u32      xaccm[8];
  51    u32      raccm;
  52    unsigned int   bytes_sent;
  53    unsigned int   bytes_rcvd;
  54 
  55    struct sk_buff   *tpkt;
  56    int      tpkt_pos;
  57    u16      tfcs;
  58    unsigned char   *optr;
  59    unsigned char   *olim;
  60    unsigned long   last_xmit;
  61 
  62    struct sk_buff   *rpkt;
  63    int      lcp_fcs;
  64    struct sk_buff_head rqueue;
  65 
  66    struct tasklet_struct tsk;
  67 
  68    atomic_t   refcnt;
  69    struct semaphore dead_sem;
  70    struct ppp_channel chan;   /* interface to generic ppp layer */
  71    unsigned char   obuf[OBUFSIZE];
  72 };
  73 
  74 /* Bit numbers in xmit_flags */
  75 #define XMIT_WAKEUP   0
  76 #define XMIT_FULL   1
  77 #define XMIT_BUSY   2
  78 
  79 /* State bits */
  80 #define SC_TOSS      1
  81 #define SC_ESCAPE   2
  82 #define SC_PREV_ERROR   4
  83 
  84 /* Bits in rbits */
  85 #define SC_RCV_BITS   (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
  86 
  87 static int flag_time = HZ;
 
- 88 module_param(flag_time, int, 0);
 - 88 return ( & ( flag_time ) )
  89 MODULE_PARM_DESC(flag_time, "ppp_async: interval between flagged packets (in clock ticks)");
  90 MODULE_LICENSE("GPL");
  91 MODULE_ALIAS_LDISC(N_PPP);
  92 
  93 /*
  94  * Prototypes.
  95  */
  96 static int ppp_async_encode(struct asyncppp *ap);
  97 static int ppp_async_send(struct ppp_channel *chan, struct sk_buff *skb);
  98 static int ppp_async_push(struct asyncppp *ap);
  99 static void ppp_async_flush_output(struct asyncppp *ap);
  100 static void ppp_async_input(struct asyncppp *ap, const unsigned char *buf,
  101              char *flags, int count);
  102 static int ppp_async_ioctl(struct ppp_channel *chan, unsigned int cmd,
  103             unsigned long arg);
  104 static void ppp_async_process(unsigned long arg);
  105 
  106 static void async_lcp_peek(struct asyncppp *ap, unsigned char *data,
  107             int len, int inbound);
  108 
  109 static struct ppp_channel_ops async_ops = {
  110    ppp_async_send,
  111    ppp_async_ioctl
  112 };
  113 
  114 /*
  115  * Routines implementing the PPP line discipline.
  116  */
  117 
  118 /*
  119  * We have a potential race on dereferencing tty->disc_data,
  120  * because the tty layer provides no locking at all - thus one
  121  * cpu could be running ppp_asynctty_receive while another
  122  * calls ppp_asynctty_close, which zeroes tty->disc_data and
  123  * frees the memory that ppp_asynctty_receive is using.  The best
  124  * way to fix this is to use a rwlock in the tty struct, but for now
  125  * we use a single global rwlock for all ttys in ppp line discipline.
  126  *
  127  * FIXME: this is no longer true. The _close path for the ldisc is 
  128  * now guaranteed to be sane. 
  129  */
  130 static DEFINE_RWLOCK(disc_data_lock);
  131 
 
- 132 static struct asyncppp *ap_get(struct tty_struct *tty)
  133 {
  134    struct asyncppp *ap;
  135 
    136    read_lock(&disc_data_lock);
    136   do
- 136   do-while (0)
- 136 do-while (0)
  137    ap = tty->disc_data;
- 138    if (ap != NULL)
  139       atomic_inc(&ap->refcnt);
    140    read_unlock(&disc_data_lock);
    140   do
- 140   do-while (0)
- 140 do-while (0)
 - 141    return ap;
  142 }
  143 
 
- 144 static void ap_put(struct asyncppp *ap)
  145 {
- 146    if (atomic_dec_and_test(&ap->refcnt))
  147       up(&ap->dead_sem);
  148 }
  149 
  150 /*
  151  * Called when a tty is put into PPP line discipline. Called in process
  152  * context.
  153  */
  154 static int
 
- 155 ppp_asynctty_open(struct tty_struct *tty)
  156 {
  157    struct asyncppp *ap;
  158    int err;
  159 
  160    err = -ENOMEM;
  161    ap = kmalloc(sizeof(*ap), GFP_KERNEL);
- 162    if (ap == 0)
 - 163       goto out;
  164 
  165    /* initialize the asyncppp structure */
  166    memset(ap, 0, sizeof(*ap));
  167    ap->tty = tty;
  168    ap->mru = PPP_MRU;
    169    spin_lock_init(&ap->xmit_lock);
- 169 do-while (0)
    170    spin_lock_init(&ap->recv_lock);
- 170 do-while (0)
  171    ap->xaccm[0] = ~0U;
  172    ap->xaccm[3] = 0x60000000U;
  173    ap->raccm = ~0U;
  174    ap->optr = ap->obuf;
  175    ap->olim = ap->obuf;
  176    ap->lcp_fcs = -1;
  177 
  178    skb_queue_head_init(&ap->rqueue);
  179    tasklet_init(&ap->tsk, ppp_async_process, (unsigned long) ap);
  180 
  181    atomic_set(&ap->refcnt, 1);
  182    init_MUTEX_LOCKED(&ap->dead_sem);
  183 
  184    ap->chan.private = ap;
  185    ap->chan.ops = &async_ops;
  186    ap->chan.mtu = PPP_MRU;
  187    err = ppp_register_channel(&ap->chan);
- 188    if (err)
 - 189       goto out_free;
  190 
  191    tty->disc_data = ap;
  192    tty->receive_room = 65536;
 - 193    return 0;
  194 
  195  out_free:
  196    kfree(ap);
  197  out:
 - 198    return err;
  199 }
  200 
  201 /*
  202  * Called when the tty is put into another line discipline
  203  * or it hangs up.  We have to wait for any cpu currently
  204  * executing in any of the other ppp_asynctty_* routines to
  205  * finish before we can call ppp_unregister_channel and free
  206  * the asyncppp struct.  This routine must be called from
  207  * process context, not interrupt or softirq context.
  208  */
  209 static void
 
- 210 ppp_asynctty_close(struct tty_struct *tty)
  211 {
  212    struct asyncppp *ap;
  213 
    214    write_lock_irq(&disc_data_lock);
    214   do
    214     do
- 214     do-while (0)
- 214   do-while (0)
- 214 do-while (0)
  215    ap = tty->disc_data;
  216    tty->disc_data = NULL;
    217    write_unlock_irq(&disc_data_lock);
    217   do
    217     do
- 217     do-while (0)
- 217   do-while (0)
- 217 do-while (0)
- 218    if (ap == 0)
 - 219       return;
  220 
  221    /*
  222     * We have now ensured that nobody can start using ap from now
  223     * on, but we have to wait for all existing users to finish.
  224     * Note that ppp_unregister_channel ensures that no calls to
  225     * our channel ops (i.e. ppp_async_send/ioctl) are in progress
  226     * by the time it returns.
  227     */
- 228    if (!atomic_dec_and_test(&ap->refcnt))
  229       down(&ap->dead_sem);
  230    tasklet_kill(&ap->tsk);
  231 
  232    ppp_unregister_channel(&ap->chan);
- 233    if (ap->rpkt != 0)
  234       kfree_skb(ap->rpkt);
  235    skb_queue_purge(&ap->rqueue);
- 236    if (ap->tpkt != 0)
  237       kfree_skb(ap->tpkt);
  238    kfree(ap);
  239 }
  240 
  241 /*
  242  * Called on tty hangup in process context.
  243  *
  244  * Wait for I/O to driver to complete and unregister PPP channel.
  245  * This is already done by the close routine, so just call that.
  246  */
 
- 247 static int ppp_asynctty_hangup(struct tty_struct *tty)
  248 {
  249    ppp_asynctty_close(tty);
 - 250    return 0;
  251 }
  252 
  253 /*
  254  * Read does nothing - no data is ever available this way.
  255  * Pppd reads and writes packets via /dev/ppp instead.
  256  */
  257 static ssize_t
 
- 258 ppp_asynctty_read(struct tty_struct *tty, struct file *file,
  259         unsigned char __user *buf, size_t count)
  260 {
 - 261    return -EAGAIN;
  262 }
  263 
  264 /*
  265  * Write on the tty does nothing, the packets all come in
  266  * from the ppp generic stuff.
  267  */
  268 static ssize_t
 
- 269 ppp_asynctty_write(struct tty_struct *tty, struct file *file,
  270          const unsigned char *buf, size_t count)
  271 {
 - 272    return -EAGAIN;
  273 }
  274 
  275 /*
  276  * Called in process context only. May be re-entered by multiple
  277  * ioctl calling threads.
  278  */
  279  
  280 static int
 
- 281 ppp_asynctty_ioctl(struct tty_struct *tty, struct file *file,
  282          unsigned int cmd, unsigned long arg)
  283 {
  284    struct asyncppp *ap = ap_get(tty);
  285    int err, val;
  286    int __user *p = (int __user *)arg;
  287 
- 288    if (ap == 0)
 - 289       return -ENXIO;
  290    err = -EFAULT;
    291    switch (cmd) {
 - 292    case PPPIOCGCHAN:
  293       err = -ENXIO;
- 294       if (ap == 0)
 - 295          break;
  296       err = -EFAULT;
- 297       if (put_user(ppp_channel_index(&ap->chan), p))
 - 298          break;
  299       err = 0;
 - 300       break;
  301 
 - 302    case PPPIOCGUNIT:
  303       err = -ENXIO;
- 304       if (ap == 0)
 - 305          break;
  306       err = -EFAULT;
- 307       if (put_user(ppp_unit_number(&ap->chan), p))
 - 308          break;
  309       err = 0;
 - 310       break;
  311 
 - 312    case TCGETS:
 - 313    case TCGETA:
  314       err = n_tty_ioctl(tty, file, cmd, arg);
 - 315       break;
  316 
 - 317    case TCFLSH:
  318       /* flush our buffers and the serial port's buffer */
- 319       if (arg == TCIOFLUSH || arg == TCOFLUSH)
 - 319     T || _
 - 319     F || T
 - 319     F || F
  320          ppp_async_flush_output(ap);
  321       err = n_tty_ioctl(tty, file, cmd, arg);
 - 322       break;
  323 
 - 324    case FIONREAD:
  325       val = 0;
- 326       if (put_user(val, p))
 - 327          break;
  328       err = 0;
 - 329       break;
  330 
 - 331    default:
  332       err = -ENOIOCTLCMD;
  333    }
  334 
  335    ap_put(ap);
 - 336    return err;
  337 }
  338 
  339 /* No kernel lock - fine */
  340 static unsigned int
 
- 341 ppp_asynctty_poll(struct tty_struct *tty, struct file *file, poll_table *wait)
  342 {
 - 343    return 0;
  344 }
  345 
  346 /*
  347  * This can now be called from hard interrupt level as well
  348  * as soft interrupt level or mainline.
  349  */
  350 static void
 
- 351 ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf,
  352         char *cflags, int count)
  353 {
  354    struct asyncppp *ap = ap_get(tty);
  355    unsigned long flags;
  356 
- 357    if (ap == 0)
 - 358       return;
    359    spin_lock_irqsave(&ap->recv_lock, flags);
    359   do
    359     do
- 359     do-while (0)
- 359   do-while (0)
    359   do
    359     do
- 359     do-while (0)
- 359   do-while (0)
- 359 do-while (0)
  360    ppp_async_input(ap, buf, cflags, count);
    361    spin_unlock_irqrestore(&ap->recv_lock, flags);
    361   do
    361     do
- 361     do-while (0)
- 361   do-while (0)
- 361 do-while (0)
- 362    if (!skb_queue_empty(&ap->rqueue))
  363       tasklet_schedule(&ap->tsk);
  364    ap_put(ap);
  365    if (test_and_clear_bit(TTY_THROTTLED, &tty->flags)
- 366        && tty->driver->unthrottle)
 - 366   T && T
 - 366   T && F
 - 366   F && _
  367       tty->driver->unthrottle(tty);
  368 }
  369 
  370 static void
 
- 371 ppp_asynctty_wakeup(struct tty_struct *tty)
  372 {
  373    struct asyncppp *ap = ap_get(tty);
  374 
  375    clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
- 376    if (ap == 0)
 - 377       return;
  378    set_bit(XMIT_WAKEUP, &ap->xmit_flags);
  379    tasklet_schedule(&ap->tsk);
  380    ap_put(ap);
  381 }
  382 
  383 
  384 static struct tty_ldisc ppp_ldisc = {
  385    .owner  = THIS_MODULE,
  386    .magic   = TTY_LDISC_MAGIC,
  387    .name   = "ppp",
  388    .open   = ppp_asynctty_open,
  389    .close   = ppp_asynctty_close,
  390    .hangup   = ppp_asynctty_hangup,
  391    .read   = ppp_asynctty_read,
  392    .write   = ppp_asynctty_write,
  393    .ioctl   = ppp_asynctty_ioctl,
  394    .poll   = ppp_asynctty_poll,
  395    .receive_buf = ppp_asynctty_receive,
  396    .write_wakeup = ppp_asynctty_wakeup,
  397 };
  398 
  399 static int __init
 
- 400 ppp_async_init(void)
  401 {
  402    int err;
  403 
  404    err = tty_register_ldisc(N_PPP, &ppp_ldisc);
- 405    if (err != 0)
  406       printk(KERN_ERR "PPP_async: error %d registering line disc.\n",
  407              err);
 - 408    return err;
  409 }
  410 
  411 /*
  412  * The following routines provide the PPP channel interface.
  413  */
  414 static int
 
- 415 ppp_async_ioctl(struct ppp_channel *chan, unsigned int cmd, unsigned long arg)
  416 {
  417    struct asyncppp *ap = chan->private;
  418    void __user *argp = (void __user *)arg;
  419    int __user *p = argp;
  420    int err, val;
  421    u32 accm[8];
  422 
  423    err = -EFAULT;
    424    switch (cmd) {
 - 425    case PPPIOCGFLAGS:
  426       val = ap->flags | ap->rbits;
- 427       if (put_user(val, p))
 - 428          break;
  429       err = 0;
 - 430       break;
 - 431    case PPPIOCSFLAGS:
- 432       if (get_user(val, p))
 - 433          break;
  434       ap->flags = val & ~SC_RCV_BITS;
    435       spin_lock_irq(&ap->recv_lock);
    435     do
    435       do
- 435       do-while (0)
- 435     do-while (0)
- 435   do-while (0)
  436       ap->rbits = val & SC_RCV_BITS;
    437       spin_unlock_irq(&ap->recv_lock);
    437     do
    437       do
- 437       do-while (0)
- 437     do-while (0)
- 437   do-while (0)
  438       err = 0;
 - 439       break;
  440 
 - 441    case PPPIOCGASYNCMAP:
- 442       if (put_user(ap->xaccm[0], (u32 __user *)argp))
 - 443          break;
  444       err = 0;
 - 445       break;
 - 446    case PPPIOCSASYNCMAP:
- 447       if (get_user(ap->xaccm[0], (u32 __user *)argp))
 - 448          break;
  449       err = 0;
 - 450       break;
  451 
 - 452    case PPPIOCGRASYNCMAP:
- 453       if (put_user(ap->raccm, (u32 __user *)argp))
 - 454          break;
  455       err = 0;
 - 456       break;
 - 457    case PPPIOCSRASYNCMAP:
- 458       if (get_user(ap->raccm, (u32 __user *)argp))
 - 459          break;
  460       err = 0;
 - 461       break;
  462 
 - 463    case PPPIOCGXASYNCMAP:
- 464       if (copy_to_user(argp, ap->xaccm, sizeof(ap->xaccm)))
 - 465          break;
  466       err = 0;
 - 467       break;
 - 468    case PPPIOCSXASYNCMAP:
- 469       if (copy_from_user(accm, argp, sizeof(accm)))
 - 470          break;
  471       accm[2] &= ~0x40000000U;   /* can't escape 0x5e */
  472       accm[3] |= 0x60000000U;      /* must escape 0x7d, 0x7e */
  473       memcpy(ap->xaccm, accm, sizeof(ap->xaccm));
  474       err = 0;
 - 475       break;
  476 
 - 477    case PPPIOCGMRU:
- 478       if (put_user(ap->mru, p))
 - 479          break;
  480       err = 0;
 - 481       break;
 - 482    case PPPIOCSMRU:
- 483       if (get_user(val, p))
 - 484          break;
- 485       if (val < PPP_MRU)
  486          val = PPP_MRU;
  487       ap->mru = val;
  488       err = 0;
 - 489