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

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


File: drivers/usb/mon/mon_text.c
Instrumentation mode: function-decision-multicondition
TER: 0 % ( 0/139)

Start/ End/    
True False - Line Source

  1 /*
  2  * The USB Monitor, inspired by Dave Harding's USBMon.
  3  *
  4  * This is a text format reader.
  5  */
  6 
  7 #include <linux/kernel.h>
  8 #include <linux/list.h>
  9 #include <linux/usb.h>
  10 #include <linux/time.h>
  11 #include <asm/uaccess.h>
  12 
  13 #include "usb_mon.h"
  14 
  15 /*
  16  * No, we do not want arbitrarily long data strings.
  17  * Use the binary interface if you want to capture bulk data!
  18  */
  19 #define DATA_MAX  32
  20 
  21 /*
  22  * Defined by USB 2.0 clause 9.3, table 9.2.
  23  */
  24 #define SETUP_MAX  8
  25 
  26 /*
  27  * This limit exists to prevent OOMs when the user process stops reading.
  28  */
  29 #define EVENT_MAX  25
  30 
  31 #define PRINTF_DFL  130
  32 
  33 struct mon_event_text {
  34    struct list_head e_link;
  35    int type;      /* submit, complete, etc. */
  36    unsigned int pipe;   /* Pipe */
  37    unsigned long id;   /* From pointer, most of the time */
  38    unsigned int tstamp;
  39    int length;      /* Depends on type: xfer length or act length */
  40    int status;
  41    char setup_flag;
  42    char data_flag;
  43    unsigned char setup[SETUP_MAX];
  44    unsigned char data[DATA_MAX];
  45 };
  46 
  47 #define SLAB_NAME_SZ  30
  48 struct mon_reader_text {
  49    kmem_cache_t *e_slab;
  50    int nevents;
  51    struct list_head e_list;
  52    struct mon_reader r;   /* In C, parent class can be placed anywhere */
  53 
  54    wait_queue_head_t wait;
  55    int printf_size;
  56    char *printf_buf;
  57    struct semaphore printf_lock;
  58 
  59    char slab_name[SLAB_NAME_SZ];
  60 };
  61 
  62 static void mon_text_ctor(void *, kmem_cache_t *, unsigned long);
  63 static void mon_text_dtor(void *, kmem_cache_t *, unsigned long);
  64 
  65 /*
  66  * mon_text_submit
  67  * mon_text_complete
  68  *
  69  * May be called from an interrupt.
  70  *
  71  * This is called with the whole mon_bus locked, so no additional lock.
  72  */
  73 
 
- 74 static inline char mon_text_get_setup(struct mon_event_text *ep,
  75     struct urb *urb, char ev_type)
  76 {
  77 
- 78    if (!usb_pipecontrol(urb->pipe) || ev_type != 'S')
 - 78   !(T) || T
 - 78   !(F) || _
 - 78   !(T) || F
 - 79       return '-';
  80 
- 81    if (urb->transfer_flags & URB_NO_SETUP_DMA_MAP)
 - 82       return mon_dmapeek(ep->setup, urb->setup_dma, SETUP_MAX);
- 83    if (urb->setup_packet == NULL)
 - 84       return 'Z';   /* '0' would be not as pretty. */
  85 
  86    memcpy(ep->setup, urb->setup_packet, SETUP_MAX);
 - 87    return 0;
  88 }
  89 
 
- 90 static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
  91     int len, char ev_type)
  92 {
  93    int pipe = urb->pipe;
  94 
- 95    if (len <= 0)
 - 96       return 'L';
- 97    if (len >= DATA_MAX)
  98       len = DATA_MAX;
  99 
- 100    if (usb_pipein(pipe)) {
- 101       if (ev_type == 'S')
 - 102          return '<';
    103    } else {
- 104       if (ev_type == 'C')
 - 105          return '>';
  106    }
  107 
  108    /*
  109     * The check to see if it's safe to poke at data has an enormous
  110     * number of corner cases, but it seems that the following is
  111     * more or less safe.
  112     *
  113     * We do not even try to look transfer_buffer, because it can
  114     * contain non-NULL garbage in case the upper level promised to
  115     * set DMA for the HCD.
  116     */
- 117    if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)
 - 118       return mon_dmapeek(ep->data, urb->transfer_dma, len);
  119 
- 120    if (urb->transfer_buffer == NULL)
 - 121       return 'Z';   /* '0' would be not as pretty. */
  122 
  123    memcpy(ep->data, urb->transfer_buffer, len);
 - 124    return 0;
  125 }
  126 
 
- 127 static inline unsigned int mon_get_timestamp(void)
  128 {
  129    struct timeval tval;
  130    unsigned int stamp;
  131 
  132    do_gettimeofday(&tval);
  133    stamp = tval.tv_sec & 0xFFFF;   /* 2^32 = 4294967296. Limit to 4096s. */
  134    stamp = stamp * 1000000 + tval.tv_usec;
 - 135    return stamp;
  136 }
  137 
 
- 138 static void mon_text_event(struct mon_reader_text *rp, struct urb *urb,
  139     char ev_type)
  140 {
  141    struct mon_event_text *ep;
  142    unsigned int stamp;
  143 
  144    stamp = mon_get_timestamp();
  145 
  146    if (rp->nevents >= EVENT_MAX ||
- 147        (ep = kmem_cache_alloc(rp->e_slab, SLAB_ATOMIC)) == NULL) {
 - 147   T || _
 - 147   F || T
 - 147   F || F
  148       rp->r.m_bus->cnt_text_lost++;
 - 149       return;
  150    }
  151 
  152    ep->type = ev_type;
  153    ep->pipe = urb->pipe;
  154    ep->id = (unsigned long) urb;
  155    ep->tstamp = stamp;
    156    ep->length = (ev_type == 'S') ?
- 156 ternary-?: ( ev_type == 'S' )
  157        urb->transfer_buffer_length : urb->actual_length;
  158    /* Collecting status makes debugging sense for submits, too */
  159    ep->status = urb->status;
  160 
  161    ep->setup_flag = mon_text_get_setup(ep, urb, ev_type);
  162    ep->data_flag = mon_text_get_data(ep, urb, ep->length, ev_type);
  163 
  164    rp->nevents++;
  165    list_add_tail(&ep->e_link, &rp->e_list);
  166    wake_up(&rp->wait);
  167 }
  168 
 
- 169 static void mon_text_submit(void *data, struct urb *urb)
  170 {
  171    struct mon_reader_text *rp = data;
  172    mon_text_event(rp, urb, 'S');
  173 }
  174 
 
- 175 static void mon_text_complete(void *data, struct urb *urb)
  176 {
  177    struct mon_reader_text *rp = data;
  178    mon_text_event(rp, urb, 'C');
  179 }
  180 
  181 /*
  182  * Fetch next event from the circular buffer.
  183  */
 
- 184 static struct mon_event_text *mon_text_fetch(struct mon_reader_text *rp,
  185     struct mon_bus *mbus)
  186 {
  187    struct list_head *p;
  188    unsigned long flags;
  189 
    190    spin_lock_irqsave(&mbus->lock, flags);
    190   do
    190     do
- 190     do-while (0)
- 190   do-while (0)
    190   do
    190     do
- 190     do-while (0)
- 190   do-while (0)
- 190 do-while (0)
- 191    if (list_empty(&rp->e_list)) {
    192       spin_unlock_irqrestore(&mbus->lock, flags);
    192     do
    192       do
- 192       do-while (0)
- 192     do-while (0)
- 192   do-while (0)
 - 193       return NULL;
  194    }
  195    p = rp->e_list.next;
  196    list_del(p);
  197    --rp->nevents;
    198    spin_unlock_irqrestore(&mbus->lock, flags);
    198   do
    198     do
- 198     do-while (0)
- 198   do-while (0)
- 198 do-while (0)
 - 199    return list_entry(p, struct mon_event_text, e_link);
  200 }
  201 
  202 /*
  203  */
 
- 204 static int mon_text_open(struct inode *inode, struct file *file)
  205 {
  206    struct mon_bus *mbus;
  207    struct usb_bus *ubus;
  208    struct mon_reader_text *rp;
  209    int rc;
  210 
  211    down(&mon_lock);
  212    mbus = inode->u.generic_ip;
  213    ubus = mbus->u_bus;
  214 
  215    rp = kmalloc(sizeof(struct mon_reader_text), GFP_KERNEL);
- 216    if (rp == NULL) {
  217       rc = -ENOMEM;
 - 218       goto err_alloc;
  219    }
  220    memset(rp, 0, sizeof(struct mon_reader_text));
  221    INIT_LIST_HEAD(&rp->e_list);
  222    init_waitqueue_head(&rp->wait);
  223    init_MUTEX(&rp->printf_lock);
  224 
  225    rp->printf_size = PRINTF_DFL;
  226    rp->printf_buf = kmalloc(rp->printf_size, GFP_KERNEL);
- 227    if (rp->printf_buf == NULL) {
  228       rc = -ENOMEM;
 - 229       goto err_alloc_pr;
  230    }
  231 
  232    rp->r.m_bus = mbus;
  233    rp->r.r_data = rp;
  234    rp->r.rnf_submit = mon_text_submit;
  235    rp->r.rnf_complete = mon_text_complete;
  236 
  237    snprintf(rp->slab_name, SLAB_NAME_SZ, "mon%dt_%lx", ubus->busnum,
  238        (long)rp);
  239    rp->e_slab = kmem_cache_create(rp->slab_name,
  240        sizeof(struct mon_event_text), sizeof(long), 0,
  241        mon_text_ctor, mon_text_dtor);
- 242    if (rp->e_slab == NULL) {
  243       rc = -ENOMEM;
 - 244       goto err_slab;
  245    }
  246 
  247    mon_reader_add(mbus, &rp->r);
  248 
  249    file->private_data = rp;
  250    up(&mon_lock);
 - 251    return 0;
  252 
  253 // err_busy:
  254 //   kmem_cache_destroy(rp->e_slab);
  255 err_slab:
  256    kfree(rp->printf_buf);
  257 err_alloc_pr:
  258    kfree(rp);
  259 err_alloc:
  260    up(&mon_lock);
 - 261    return rc;
  262 }
  263 
  264 /*
  265  * For simplicity, we read one record in one system call and throw out
  266  * what does not fit. This means that the following does not work:
  267  *   dd if=/dbg/usbmon/0t bs=10
  268  * Also, we do not allow seeks and do not bother advancing the offset.
  269  */
 
- 270 static ssize_t mon_text_read(struct file *file, char __user *buf,
  271             size_t nbytes, loff_t *ppos)
  272 {
  273    struct mon_reader_text *rp = file->private_data;
  274    struct mon_bus *mbus = rp->r.m_bus;
  275    DECLARE_WAITQUEUE(waita, current);
  276    struct mon_event_text *ep;
  277    int cnt, limit;
  278    char *pbuf;
  279    char udir, utype;
  280    int data_len, i;
  281 
  282    add_wait_queue(&rp->wait, &waita);
    283    set_current_state(TASK_INTERRUPTIBLE);
- 283 do-while (0)
- 284    while ((ep = mon_text_fetch(rp, mbus)) == NULL) {
- 285       if (file->f_flags & O_NONBLOCK) {
    286          set_current_state(TASK_RUNNING);
- 286     do-while (0)
  287          remove_wait_queue(&rp->wait, &waita);
 - 288          return -EWOULDBLOCK;   /* Same as EAGAIN in Linux */
  289       }
  290       /*
  291        * We do not count nwaiters, because ->release is supposed
  292        * to be called when all openers are gone only.
  293        */
  294       schedule();
- 295       if (signal_pending(current)) {
  296          remove_wait_queue(&rp->wait, &waita);
 - 297          return -EINTR;
  298       }
    299       set_current_state(TASK_INTERRUPTIBLE);
- 299   do-while (0)
  300    }
    301    set_current_state(TASK_RUNNING);
- 301 do-while (0)
  302    remove_wait_queue(&rp->wait, &waita);
  303 
  304    down(&rp->printf_lock);
  305    cnt = 0;
  306    pbuf = rp->printf_buf;
  307    limit = rp->printf_size;
  308 
    309    udir = usb_pipein(ep->pipe) ? 'i' : 'o';
- 309 ternary-?: ( ( ep -> pipe ) & 0x80 )
    310    switch (usb_pipetype(ep->pipe)) {
 - 311    case PIPE_ISOCHRONOUS:   utype = 'Z'; break;
 - 311   break
 - 312    case PIPE_INTERRUPT:   utype = 'I'; break;
 - 312   break
 - 313    case PIPE_CONTROL:   utype = 'C'; break;
 - 313   break
 - 314    default: /* PIPE_BULK */  utype = 'B';
  315    }
  316    cnt += snprintf(pbuf + cnt, limit - cnt,
  317        "%lx %u %c %c%c:%03u:%02u",
  318        ep->id, ep->tstamp, ep->type,
  319        utype, udir, usb_pipedevice(ep->pipe), usb_pipeendpoint(ep->pipe));
  320 
- 321    if (ep->setup_flag == 0) {   /* Setup packet is present and captured */
  322       cnt += snprintf(pbuf + cnt, limit - cnt,
  323           " s %02x %02x %04x %04x %04x",
  324           ep->setup[0],
  325           ep->setup[1],
  326           (ep->setup[3] << 8) | ep->setup[2],
  327           (ep->setup[5] << 8) | ep->setup[4],
  328           (ep->setup[7] << 8) | ep->setup[6]);
- 329    } else if (ep->setup_flag != '-') { /* Unable to capture setup packet */
  330       cnt += snprintf(pbuf + cnt, limit - cnt,
  331           " %c __ __ ____ ____ ____", ep->setup_flag);
    332    } else {                     /* No setup for this kind of URB */
  333       cnt += snprintf(pbuf + cnt, limit - cnt, " %d", ep->status);
  334    }
  335    cnt += snprintf(pbuf + cnt, limit - cnt, " %d", ep->length);
  336 
- 337    if ((data_len = ep->length) > 0) {
- 338       if (ep->data_flag == 0) {
  339          cnt += snprintf(pbuf + cnt, limit - cnt, " =");
- 340          if (data_len >= DATA_MAX)
  341             data_len = DATA_MAX;
- 342          for (i = 0; i < data_len; i++) {
- 343             if (i % 4 == 0) {
  344                cnt += snprintf(pbuf + cnt, limit - cnt,
  345                    " ");
  346             }
  347             cnt += snprintf(pbuf + cnt, limit - cnt,
  348                 "%02x", ep->data[i]);
  349          }
  350          cnt += snprintf(pbuf + cnt, limit - cnt, "\n");
    351       } else {
  352          cnt += snprintf(pbuf + cnt, limit - cnt,
  353              " %c\n", ep->data_flag);
  354       }
    355    } else {
  356       cnt += snprintf(pbuf + cnt, limit - cnt, "\n");
  357    }
  358 
- 359    if (copy_to_user(buf, rp->printf_buf, cnt))
  360       cnt = -EFAULT;
  361    up(&rp->printf_lock);
  362    kmem_cache_free(rp->e_slab, ep);
 - 363    return cnt;
  364 }
  365 
 
- 366 static int mon_text_release(struct inode *inode, struct file *file)
  367 {
  368    struct mon_reader_text *rp = file->private_data;
  369    struct mon_bus *mbus;
  370    /* unsigned long flags; */
  371    struct list_head *p;
  372    struct mon_event_text *ep;
  373 
  374    down(&mon_lock);
  375    mbus = inode->u.generic_ip;
  376 
- 377    if (mbus->nreaders <= 0) {
  378       printk(KERN_ERR TAG ": consistency error on close\n");
  379       up(&mon_lock);
 - 380       return 0;
  381    }
  382    mon_reader_del(mbus, &rp->r);
  383 
  384    /*
  385     * In theory, e_list is protected by mbus->lock. However,
  386     * after mon_reader_del has finished, the following is the case:
  387     *  - we are not on reader list anymore, so new events won't be added;
  388     *  - whole mbus may be dropped if it was orphaned.
  389     * So, we better not touch mbus.
  390     */
  391    /* spin_lock_irqsave(&mbus->lock, flags); */
- 392    while (!list_empty(&rp->e_list)) {
  393       p = rp->e_list.next;
  394       ep = list_entry(p, struct mon_event_text, e_link);
  395       list_del(p);
  396       --rp->nevents;
  397       kmem_cache_free(rp->e_slab, ep);
  398    }
  399    /* spin_unlock_irqrestore(&mbus->lock, flags); */
  400 
  401    kmem_cache_destroy(rp->e_slab);
  402    kfree(rp->printf_buf);
  403    kfree(rp);
  404 
  405    up(&mon_lock);
 - 406    return 0;
  407 }
  408 
  409 struct file_operations mon_fops_text = {
  410    .owner =   THIS_MODULE,
  411    .open =      mon_text_open,
  412    .llseek =   no_llseek,
  413    .read =      mon_text_read,
  414    /* .write =   mon_text_write, */
  415    /* .poll =      mon_text_poll, */
  416    /* .ioctl =   mon_text_ioctl, */
  417    .release =   mon_text_release,
  418 };
  419 
  420 /*
  421  * Slab interface: constructor.
  422  */
 
- 423 static void mon_text_ctor(void *mem, kmem_cache_t *slab, unsigned long sflags)
  424 {
  425    /*
  426     * Nothing to initialize. No, really!
  427     * So, we fill it with garbage to emulate a reused object.
  428     */
  429    memset(mem, 0xe5, sizeof(struct mon_event_text));
  430 }
  431 
 
- 432 static void mon_text_dtor(void *mem, kmem_cache_t *slab, unsigned long sflags)
  433 {
  434    ;
  435 }
***TER 0% (0/139) of SOURCE FILE mon_text.c

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