LCOV - code coverage report
Current view: top level - drivers/usb/mon - mon_bin.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 18 617 2.9 %
Date: 2022-04-01 14:17:54 Functions: 2 27 7.4 %
Branches: 6 257 2.3 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0
       2                 :            : /*
       3                 :            :  * The USB Monitor, inspired by Dave Harding's USBMon.
       4                 :            :  *
       5                 :            :  * This is a binary format reader.
       6                 :            :  *
       7                 :            :  * Copyright (C) 2006 Paolo Abeni (paolo.abeni@email.it)
       8                 :            :  * Copyright (C) 2006,2007 Pete Zaitcev (zaitcev@redhat.com)
       9                 :            :  */
      10                 :            : 
      11                 :            : #include <linux/kernel.h>
      12                 :            : #include <linux/sched/signal.h>
      13                 :            : #include <linux/types.h>
      14                 :            : #include <linux/fs.h>
      15                 :            : #include <linux/cdev.h>
      16                 :            : #include <linux/export.h>
      17                 :            : #include <linux/usb.h>
      18                 :            : #include <linux/poll.h>
      19                 :            : #include <linux/compat.h>
      20                 :            : #include <linux/mm.h>
      21                 :            : #include <linux/scatterlist.h>
      22                 :            : #include <linux/slab.h>
      23                 :            : #include <linux/time64.h>
      24                 :            : 
      25                 :            : #include <linux/uaccess.h>
      26                 :            : 
      27                 :            : #include "usb_mon.h"
      28                 :            : 
      29                 :            : /*
      30                 :            :  * Defined by USB 2.0 clause 9.3, table 9.2.
      31                 :            :  */
      32                 :            : #define SETUP_LEN  8
      33                 :            : 
      34                 :            : /* ioctl macros */
      35                 :            : #define MON_IOC_MAGIC 0x92
      36                 :            : 
      37                 :            : #define MON_IOCQ_URB_LEN _IO(MON_IOC_MAGIC, 1)
      38                 :            : /* #2 used to be MON_IOCX_URB, removed before it got into Linus tree */
      39                 :            : #define MON_IOCG_STATS _IOR(MON_IOC_MAGIC, 3, struct mon_bin_stats)
      40                 :            : #define MON_IOCT_RING_SIZE _IO(MON_IOC_MAGIC, 4)
      41                 :            : #define MON_IOCQ_RING_SIZE _IO(MON_IOC_MAGIC, 5)
      42                 :            : #define MON_IOCX_GET   _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get)
      43                 :            : #define MON_IOCX_MFETCH _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch)
      44                 :            : #define MON_IOCH_MFLUSH _IO(MON_IOC_MAGIC, 8)
      45                 :            : /* #9 was MON_IOCT_SETAPI */
      46                 :            : #define MON_IOCX_GETX   _IOW(MON_IOC_MAGIC, 10, struct mon_bin_get)
      47                 :            : 
      48                 :            : #ifdef CONFIG_COMPAT
      49                 :            : #define MON_IOCX_GET32 _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get32)
      50                 :            : #define MON_IOCX_MFETCH32 _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch32)
      51                 :            : #define MON_IOCX_GETX32   _IOW(MON_IOC_MAGIC, 10, struct mon_bin_get32)
      52                 :            : #endif
      53                 :            : 
      54                 :            : /*
      55                 :            :  * Some architectures have enormous basic pages (16KB for ia64, 64KB for ppc).
      56                 :            :  * But it's all right. Just use a simple way to make sure the chunk is never
      57                 :            :  * smaller than a page.
      58                 :            :  *
      59                 :            :  * N.B. An application does not know our chunk size.
      60                 :            :  *
      61                 :            :  * Woops, get_zeroed_page() returns a single page. I guess we're stuck with
      62                 :            :  * page-sized chunks for the time being.
      63                 :            :  */
      64                 :            : #define CHUNK_SIZE   PAGE_SIZE
      65                 :            : #define CHUNK_ALIGN(x)   (((x)+CHUNK_SIZE-1) & ~(CHUNK_SIZE-1))
      66                 :            : 
      67                 :            : /*
      68                 :            :  * The magic limit was calculated so that it allows the monitoring
      69                 :            :  * application to pick data once in two ticks. This way, another application,
      70                 :            :  * which presumably drives the bus, gets to hog CPU, yet we collect our data.
      71                 :            :  * If HZ is 100, a 480 mbit/s bus drives 614 KB every jiffy. USB has an
      72                 :            :  * enormous overhead built into the bus protocol, so we need about 1000 KB.
      73                 :            :  *
      74                 :            :  * This is still too much for most cases, where we just snoop a few
      75                 :            :  * descriptor fetches for enumeration. So, the default is a "reasonable"
      76                 :            :  * amount for systems with HZ=250 and incomplete bus saturation.
      77                 :            :  *
      78                 :            :  * XXX What about multi-megabyte URBs which take minutes to transfer?
      79                 :            :  */
      80                 :            : #define BUFF_MAX  CHUNK_ALIGN(1200*1024)
      81                 :            : #define BUFF_DFL   CHUNK_ALIGN(300*1024)
      82                 :            : #define BUFF_MIN     CHUNK_ALIGN(8*1024)
      83                 :            : 
      84                 :            : /*
      85                 :            :  * The per-event API header (2 per URB).
      86                 :            :  *
      87                 :            :  * This structure is seen in userland as defined by the documentation.
      88                 :            :  */
      89                 :            : struct mon_bin_hdr {
      90                 :            :         u64 id;                 /* URB ID - from submission to callback */
      91                 :            :         unsigned char type;     /* Same as in text API; extensible. */
      92                 :            :         unsigned char xfer_type;        /* ISO, Intr, Control, Bulk */
      93                 :            :         unsigned char epnum;    /* Endpoint number and transfer direction */
      94                 :            :         unsigned char devnum;   /* Device address */
      95                 :            :         unsigned short busnum;  /* Bus number */
      96                 :            :         char flag_setup;
      97                 :            :         char flag_data;
      98                 :            :         s64 ts_sec;             /* ktime_get_real_ts64 */
      99                 :            :         s32 ts_usec;            /* ktime_get_real_ts64 */
     100                 :            :         int status;
     101                 :            :         unsigned int len_urb;   /* Length of data (submitted or actual) */
     102                 :            :         unsigned int len_cap;   /* Delivered length */
     103                 :            :         union {
     104                 :            :                 unsigned char setup[SETUP_LEN]; /* Only for Control S-type */
     105                 :            :                 struct iso_rec {
     106                 :            :                         int error_count;
     107                 :            :                         int numdesc;
     108                 :            :                 } iso;
     109                 :            :         } s;
     110                 :            :         int interval;
     111                 :            :         int start_frame;
     112                 :            :         unsigned int xfer_flags;
     113                 :            :         unsigned int ndesc;     /* Actual number of ISO descriptors */
     114                 :            : };
     115                 :            : 
     116                 :            : /*
     117                 :            :  * ISO vector, packed into the head of data stream.
     118                 :            :  * This has to take 16 bytes to make sure that the end of buffer
     119                 :            :  * wrap is not happening in the middle of a descriptor.
     120                 :            :  */
     121                 :            : struct mon_bin_isodesc {
     122                 :            :         int          iso_status;
     123                 :            :         unsigned int iso_off;
     124                 :            :         unsigned int iso_len;
     125                 :            :         u32 _pad;
     126                 :            : };
     127                 :            : 
     128                 :            : /* per file statistic */
     129                 :            : struct mon_bin_stats {
     130                 :            :         u32 queued;
     131                 :            :         u32 dropped;
     132                 :            : };
     133                 :            : 
     134                 :            : struct mon_bin_get {
     135                 :            :         struct mon_bin_hdr __user *hdr; /* Can be 48 bytes or 64. */
     136                 :            :         void __user *data;
     137                 :            :         size_t alloc;           /* Length of data (can be zero) */
     138                 :            : };
     139                 :            : 
     140                 :            : struct mon_bin_mfetch {
     141                 :            :         u32 __user *offvec;     /* Vector of events fetched */
     142                 :            :         u32 nfetch;             /* Number of events to fetch (out: fetched) */
     143                 :            :         u32 nflush;             /* Number of events to flush */
     144                 :            : };
     145                 :            : 
     146                 :            : #ifdef CONFIG_COMPAT
     147                 :            : struct mon_bin_get32 {
     148                 :            :         u32 hdr32;
     149                 :            :         u32 data32;
     150                 :            :         u32 alloc32;
     151                 :            : };
     152                 :            : 
     153                 :            : struct mon_bin_mfetch32 {
     154                 :            :         u32 offvec32;
     155                 :            :         u32 nfetch32;
     156                 :            :         u32 nflush32;
     157                 :            : };
     158                 :            : #endif
     159                 :            : 
     160                 :            : /* Having these two values same prevents wrapping of the mon_bin_hdr */
     161                 :            : #define PKT_ALIGN   64
     162                 :            : #define PKT_SIZE    64
     163                 :            : 
     164                 :            : #define PKT_SZ_API0 48  /* API 0 (2.6.20) size */
     165                 :            : #define PKT_SZ_API1 64  /* API 1 size: extra fields */
     166                 :            : 
     167                 :            : #define ISODESC_MAX   128       /* Same number as usbfs allows, 2048 bytes. */
     168                 :            : 
     169                 :            : /* max number of USB bus supported */
     170                 :            : #define MON_BIN_MAX_MINOR 128
     171                 :            : 
     172                 :            : /*
     173                 :            :  * The buffer: map of used pages.
     174                 :            :  */
     175                 :            : struct mon_pgmap {
     176                 :            :         struct page *pg;
     177                 :            :         unsigned char *ptr;     /* XXX just use page_to_virt everywhere? */
     178                 :            : };
     179                 :            : 
     180                 :            : /*
     181                 :            :  * This gets associated with an open file struct.
     182                 :            :  */
     183                 :            : struct mon_reader_bin {
     184                 :            :         /* The buffer: one per open. */
     185                 :            :         spinlock_t b_lock;              /* Protect b_cnt, b_in */
     186                 :            :         unsigned int b_size;            /* Current size of the buffer - bytes */
     187                 :            :         unsigned int b_cnt;             /* Bytes used */
     188                 :            :         unsigned int b_in, b_out;       /* Offsets into buffer - bytes */
     189                 :            :         unsigned int b_read;            /* Amount of read data in curr. pkt. */
     190                 :            :         struct mon_pgmap *b_vec;        /* The map array */
     191                 :            :         wait_queue_head_t b_wait;       /* Wait for data here */
     192                 :            : 
     193                 :            :         struct mutex fetch_lock;        /* Protect b_read, b_out */
     194                 :            :         int mmap_active;
     195                 :            : 
     196                 :            :         /* A list of these is needed for "bus 0". Some time later. */
     197                 :            :         struct mon_reader r;
     198                 :            : 
     199                 :            :         /* Stats */
     200                 :            :         unsigned int cnt_lost;
     201                 :            : };
     202                 :            : 
     203                 :          0 : static inline struct mon_bin_hdr *MON_OFF2HDR(const struct mon_reader_bin *rp,
     204                 :            :     unsigned int offset)
     205                 :            : {
     206                 :          0 :         return (struct mon_bin_hdr *)
     207                 :          0 :             (rp->b_vec[offset / CHUNK_SIZE].ptr + offset % CHUNK_SIZE);
     208                 :            : }
     209                 :            : 
     210                 :            : #define MON_RING_EMPTY(rp)      ((rp)->b_cnt == 0)
     211                 :            : 
     212                 :            : static unsigned char xfer_to_pipe[4] = {
     213                 :            :         PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
     214                 :            : };
     215                 :            : 
     216                 :            : static struct class *mon_bin_class;
     217                 :            : static dev_t mon_bin_dev0;
     218                 :            : static struct cdev mon_bin_cdev;
     219                 :            : 
     220                 :            : static void mon_buff_area_fill(const struct mon_reader_bin *rp,
     221                 :            :     unsigned int offset, unsigned int size);
     222                 :            : static int mon_bin_wait_event(struct file *file, struct mon_reader_bin *rp);
     223                 :            : static int mon_alloc_buff(struct mon_pgmap *map, int npages);
     224                 :            : static void mon_free_buff(struct mon_pgmap *map, int npages);
     225                 :            : 
     226                 :            : /*
     227                 :            :  * This is a "chunked memcpy". It does not manipulate any counters.
     228                 :            :  */
     229                 :            : static unsigned int mon_copy_to_buff(const struct mon_reader_bin *this,
     230                 :            :     unsigned int off, const unsigned char *from, unsigned int length)
     231                 :            : {
     232                 :            :         unsigned int step_len;
     233                 :            :         unsigned char *buf;
     234                 :            :         unsigned int in_page;
     235                 :            : 
     236                 :            :         while (length) {
     237                 :            :                 /*
     238                 :            :                  * Determine step_len.
     239                 :            :                  */
     240                 :            :                 step_len = length;
     241                 :            :                 in_page = CHUNK_SIZE - (off & (CHUNK_SIZE-1));
     242                 :            :                 if (in_page < step_len)
     243                 :            :                         step_len = in_page;
     244                 :            : 
     245                 :            :                 /*
     246                 :            :                  * Copy data and advance pointers.
     247                 :            :                  */
     248                 :            :                 buf = this->b_vec[off / CHUNK_SIZE].ptr + off % CHUNK_SIZE;
     249                 :            :                 memcpy(buf, from, step_len);
     250                 :            :                 if ((off += step_len) >= this->b_size) off = 0;
     251                 :            :                 from += step_len;
     252                 :            :                 length -= step_len;
     253                 :            :         }
     254                 :            :         return off;
     255                 :            : }
     256                 :            : 
     257                 :            : /*
     258                 :            :  * This is a little worse than the above because it's "chunked copy_to_user".
     259                 :            :  * The return value is an error code, not an offset.
     260                 :            :  */
     261                 :            : static int copy_from_buf(const struct mon_reader_bin *this, unsigned int off,
     262                 :            :     char __user *to, int length)
     263                 :            : {
     264                 :            :         unsigned int step_len;
     265                 :            :         unsigned char *buf;
     266                 :            :         unsigned int in_page;
     267                 :            : 
     268                 :            :         while (length) {
     269                 :            :                 /*
     270                 :            :                  * Determine step_len.
     271                 :            :                  */
     272                 :            :                 step_len = length;
     273                 :            :                 in_page = CHUNK_SIZE - (off & (CHUNK_SIZE-1));
     274                 :            :                 if (in_page < step_len)
     275                 :            :                         step_len = in_page;
     276                 :            : 
     277                 :            :                 /*
     278                 :            :                  * Copy data and advance pointers.
     279                 :            :                  */
     280                 :            :                 buf = this->b_vec[off / CHUNK_SIZE].ptr + off % CHUNK_SIZE;
     281                 :            :                 if (copy_to_user(to, buf, step_len))
     282                 :            :                         return -EINVAL;
     283                 :            :                 if ((off += step_len) >= this->b_size) off = 0;
     284                 :            :                 to += step_len;
     285                 :            :                 length -= step_len;
     286                 :            :         }
     287                 :            :         return 0;
     288                 :            : }
     289                 :            : 
     290                 :            : /*
     291                 :            :  * Allocate an (aligned) area in the buffer.
     292                 :            :  * This is called under b_lock.
     293                 :            :  * Returns ~0 on failure.
     294                 :            :  */
     295                 :          0 : static unsigned int mon_buff_area_alloc(struct mon_reader_bin *rp,
     296                 :            :     unsigned int size)
     297                 :            : {
     298                 :          0 :         unsigned int offset;
     299                 :            : 
     300                 :          0 :         size = (size + PKT_ALIGN-1) & ~(PKT_ALIGN-1);
     301                 :          0 :         if (rp->b_cnt + size > rp->b_size)
     302                 :            :                 return ~0;
     303                 :          0 :         offset = rp->b_in;
     304                 :          0 :         rp->b_cnt += size;
     305   [ #  #  #  # ]:          0 :         if ((rp->b_in += size) >= rp->b_size)
     306                 :          0 :                 rp->b_in -= rp->b_size;
     307                 :            :         return offset;
     308                 :            : }
     309                 :            : 
     310                 :            : /*
     311                 :            :  * This is the same thing as mon_buff_area_alloc, only it does not allow
     312                 :            :  * buffers to wrap. This is needed by applications which pass references
     313                 :            :  * into mmap-ed buffers up their stacks (libpcap can do that).
     314                 :            :  *
     315                 :            :  * Currently, we always have the header stuck with the data, although
     316                 :            :  * it is not strictly speaking necessary.
     317                 :            :  *
     318                 :            :  * When a buffer would wrap, we place a filler packet to mark the space.
     319                 :            :  */
     320                 :          0 : static unsigned int mon_buff_area_alloc_contiguous(struct mon_reader_bin *rp,
     321                 :            :     unsigned int size)
     322                 :            : {
     323                 :          0 :         unsigned int offset;
     324                 :          0 :         unsigned int fill_size;
     325                 :            : 
     326                 :          0 :         size = (size + PKT_ALIGN-1) & ~(PKT_ALIGN-1);
     327         [ #  # ]:          0 :         if (rp->b_cnt + size > rp->b_size)
     328                 :            :                 return ~0;
     329         [ #  # ]:          0 :         if (rp->b_in + size > rp->b_size) {
     330                 :            :                 /*
     331                 :            :                  * This would wrap. Find if we still have space after
     332                 :            :                  * skipping to the end of the buffer. If we do, place
     333                 :            :                  * a filler packet and allocate a new packet.
     334                 :            :                  */
     335                 :          0 :                 fill_size = rp->b_size - rp->b_in;
     336         [ #  # ]:          0 :                 if (rp->b_cnt + size + fill_size > rp->b_size)
     337                 :            :                         return ~0;
     338                 :          0 :                 mon_buff_area_fill(rp, rp->b_in, fill_size);
     339                 :            : 
     340                 :          0 :                 offset = 0;
     341                 :          0 :                 rp->b_in = size;
     342                 :          0 :                 rp->b_cnt += size + fill_size;
     343         [ #  # ]:          0 :         } else if (rp->b_in + size == rp->b_size) {
     344                 :          0 :                 offset = rp->b_in;
     345                 :          0 :                 rp->b_in = 0;
     346                 :          0 :                 rp->b_cnt += size;
     347                 :            :         } else {
     348                 :          0 :                 offset = rp->b_in;
     349                 :          0 :                 rp->b_in += size;
     350                 :          0 :                 rp->b_cnt += size;
     351                 :            :         }
     352                 :            :         return offset;
     353                 :            : }
     354                 :            : 
     355                 :            : /*
     356                 :            :  * Return a few (kilo-)bytes to the head of the buffer.
     357                 :            :  * This is used if a data fetch fails.
     358                 :            :  */
     359                 :          0 : static void mon_buff_area_shrink(struct mon_reader_bin *rp, unsigned int size)
     360                 :            : {
     361                 :            : 
     362                 :            :         /* size &= ~(PKT_ALIGN-1);  -- we're called with aligned size */
     363                 :          0 :         rp->b_cnt -= size;
     364                 :          0 :         if (rp->b_in < size)
     365                 :          0 :                 rp->b_in += rp->b_size;
     366                 :          0 :         rp->b_in -= size;
     367                 :          0 : }
     368                 :            : 
     369                 :            : /*
     370                 :            :  * This has to be called under both b_lock and fetch_lock, because
     371                 :            :  * it accesses both b_cnt and b_out.
     372                 :            :  */
     373                 :          0 : static void mon_buff_area_free(struct mon_reader_bin *rp, unsigned int size)
     374                 :            : {
     375                 :            : 
     376                 :          0 :         size = (size + PKT_ALIGN-1) & ~(PKT_ALIGN-1);
     377                 :          0 :         rp->b_cnt -= size;
     378                 :          0 :         if ((rp->b_out += size) >= rp->b_size)
     379                 :          0 :                 rp->b_out -= rp->b_size;
     380                 :            : }
     381                 :            : 
     382                 :          0 : static void mon_buff_area_fill(const struct mon_reader_bin *rp,
     383                 :            :     unsigned int offset, unsigned int size)
     384                 :            : {
     385                 :          0 :         struct mon_bin_hdr *ep;
     386                 :            : 
     387                 :          0 :         ep = MON_OFF2HDR(rp, offset);
     388                 :          0 :         memset(ep, 0, PKT_SIZE);
     389                 :          0 :         ep->type = '@';
     390                 :          0 :         ep->len_cap = size - PKT_SIZE;
     391                 :          0 : }
     392                 :            : 
     393                 :          0 : static inline char mon_bin_get_setup(unsigned char *setupb,
     394                 :            :     const struct urb *urb, char ev_type)
     395                 :            : {
     396                 :            : 
     397                 :          0 :         if (urb->setup_packet == NULL)
     398                 :            :                 return 'Z';
     399                 :          0 :         memcpy(setupb, urb->setup_packet, SETUP_LEN);
     400                 :          0 :         return 0;
     401                 :            : }
     402                 :            : 
     403                 :          0 : static unsigned int mon_bin_get_data(const struct mon_reader_bin *rp,
     404                 :            :     unsigned int offset, struct urb *urb, unsigned int length,
     405                 :            :     char *flag)
     406                 :            : {
     407                 :          0 :         int i;
     408                 :          0 :         struct scatterlist *sg;
     409                 :          0 :         unsigned int this_len;
     410                 :            : 
     411                 :          0 :         *flag = 0;
     412         [ #  # ]:          0 :         if (urb->num_sgs == 0) {
     413         [ #  # ]:          0 :                 if (urb->transfer_buffer == NULL) {
     414                 :          0 :                         *flag = 'Z';
     415                 :          0 :                         return length;
     416                 :            :                 }
     417                 :          0 :                 mon_copy_to_buff(rp, offset, urb->transfer_buffer, length);
     418                 :          0 :                 length = 0;
     419                 :            : 
     420                 :            :         } else {
     421                 :            :                 /* If IOMMU coalescing occurred, we cannot trust sg_page */
     422         [ #  # ]:          0 :                 if (urb->transfer_flags & URB_DMA_SG_COMBINED) {
     423                 :          0 :                         *flag = 'D';
     424                 :          0 :                         return length;
     425                 :            :                 }
     426                 :            : 
     427                 :            :                 /* Copy up to the first non-addressable segment */
     428         [ #  # ]:          0 :                 for_each_sg(urb->sg, sg, urb->num_sgs, i) {
     429         [ #  # ]:          0 :                         if (length == 0 || PageHighMem(sg_page(sg)))
     430                 :            :                                 break;
     431                 :          0 :                         this_len = min_t(unsigned int, sg->length, length);
     432                 :          0 :                         offset = mon_copy_to_buff(rp, offset, sg_virt(sg),
     433                 :            :                                         this_len);
     434                 :          0 :                         length -= this_len;
     435                 :            :                 }
     436         [ #  # ]:          0 :                 if (i == 0)
     437                 :          0 :                         *flag = 'D';
     438                 :            :         }
     439                 :            : 
     440                 :            :         return length;
     441                 :            : }
     442                 :            : 
     443                 :            : /*
     444                 :            :  * This is the look-ahead pass in case of 'C Zi', when actual_length cannot
     445                 :            :  * be used to determine the length of the whole contiguous buffer.
     446                 :            :  */
     447                 :          0 : static unsigned int mon_bin_collate_isodesc(const struct mon_reader_bin *rp,
     448                 :            :     struct urb *urb, unsigned int ndesc)
     449                 :            : {
     450                 :          0 :         struct usb_iso_packet_descriptor *fp;
     451                 :          0 :         unsigned int length;
     452                 :            : 
     453                 :          0 :         length = 0;
     454                 :          0 :         fp = urb->iso_frame_desc;
     455         [ #  # ]:          0 :         while (ndesc-- != 0) {
     456         [ #  # ]:          0 :                 if (fp->actual_length != 0) {
     457                 :          0 :                         if (fp->offset + fp->actual_length > length)
     458                 :            :                                 length = fp->offset + fp->actual_length;
     459                 :            :                 }
     460                 :          0 :                 fp++;
     461                 :            :         }
     462                 :            :         return length;
     463                 :            : }
     464                 :            : 
     465                 :          0 : static void mon_bin_get_isodesc(const struct mon_reader_bin *rp,
     466                 :            :     unsigned int offset, struct urb *urb, char ev_type, unsigned int ndesc)
     467                 :            : {
     468                 :          0 :         struct mon_bin_isodesc *dp;
     469                 :          0 :         struct usb_iso_packet_descriptor *fp;
     470                 :            : 
     471                 :          0 :         fp = urb->iso_frame_desc;
     472         [ #  # ]:          0 :         while (ndesc-- != 0) {
     473                 :          0 :                 dp = (struct mon_bin_isodesc *)
     474                 :          0 :                     (rp->b_vec[offset / CHUNK_SIZE].ptr + offset % CHUNK_SIZE);
     475                 :          0 :                 dp->iso_status = fp->status;
     476                 :          0 :                 dp->iso_off = fp->offset;
     477         [ #  # ]:          0 :                 dp->iso_len = (ev_type == 'S') ? fp->length : fp->actual_length;
     478                 :          0 :                 dp->_pad = 0;
     479         [ #  # ]:          0 :                 if ((offset += sizeof(struct mon_bin_isodesc)) >= rp->b_size)
     480                 :          0 :                         offset = 0;
     481                 :          0 :                 fp++;
     482                 :            :         }
     483                 :          0 : }
     484                 :            : 
     485                 :          0 : static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb,
     486                 :            :     char ev_type, int status)
     487                 :            : {
     488                 :          0 :         const struct usb_endpoint_descriptor *epd = &urb->ep->desc;
     489                 :          0 :         struct timespec64 ts;
     490                 :          0 :         unsigned long flags;
     491                 :          0 :         unsigned int urb_length;
     492                 :          0 :         unsigned int offset;
     493                 :          0 :         unsigned int length;
     494                 :          0 :         unsigned int delta;
     495                 :          0 :         unsigned int ndesc, lendesc;
     496                 :          0 :         unsigned char dir;
     497                 :          0 :         struct mon_bin_hdr *ep;
     498                 :          0 :         char data_tag = 0;
     499                 :            : 
     500                 :          0 :         ktime_get_real_ts64(&ts);
     501                 :            : 
     502                 :          0 :         spin_lock_irqsave(&rp->b_lock, flags);
     503                 :            : 
     504                 :            :         /*
     505                 :            :          * Find the maximum allowable length, then allocate space.
     506                 :            :          */
     507                 :          0 :         urb_length = (ev_type == 'S') ?
     508         [ #  # ]:          0 :             urb->transfer_buffer_length : urb->actual_length;
     509                 :          0 :         length = urb_length;
     510                 :            : 
     511         [ #  # ]:          0 :         if (usb_endpoint_xfer_isoc(epd)) {
     512         [ #  # ]:          0 :                 if (urb->number_of_packets < 0) {
     513                 :            :                         ndesc = 0;
     514         [ #  # ]:          0 :                 } else if (urb->number_of_packets >= ISODESC_MAX) {
     515                 :            :                         ndesc = ISODESC_MAX;
     516                 :            :                 } else {
     517                 :          0 :                         ndesc = urb->number_of_packets;
     518                 :            :                 }
     519   [ #  #  #  # ]:          0 :                 if (ev_type == 'C' && usb_urb_dir_in(urb))
     520                 :          0 :                         length = mon_bin_collate_isodesc(rp, urb, ndesc);
     521                 :            :         } else {
     522                 :            :                 ndesc = 0;
     523                 :            :         }
     524                 :          0 :         lendesc = ndesc*sizeof(struct mon_bin_isodesc);
     525                 :            : 
     526                 :            :         /* not an issue unless there's a subtle bug in a HCD somewhere */
     527                 :          0 :         if (length >= urb->transfer_buffer_length)
     528                 :            :                 length = urb->transfer_buffer_length;
     529                 :            : 
     530                 :          0 :         if (length >= rp->b_size/5)
     531                 :            :                 length = rp->b_size/5;
     532                 :            : 
     533         [ #  # ]:          0 :         if (usb_urb_dir_in(urb)) {
     534         [ #  # ]:          0 :                 if (ev_type == 'S') {
     535                 :          0 :                         length = 0;
     536                 :          0 :                         data_tag = '<';
     537                 :            :                 }
     538                 :            :                 /* Cannot rely on endpoint number in case of control ep.0 */
     539                 :            :                 dir = USB_DIR_IN;
     540                 :            :         } else {
     541         [ #  # ]:          0 :                 if (ev_type == 'C') {
     542                 :          0 :                         length = 0;
     543                 :          0 :                         data_tag = '>';
     544                 :            :                 }
     545                 :            :                 dir = 0;
     546                 :            :         }
     547                 :            : 
     548         [ #  # ]:          0 :         if (rp->mmap_active) {
     549                 :          0 :                 offset = mon_buff_area_alloc_contiguous(rp,
     550                 :          0 :                                                  length + PKT_SIZE + lendesc);
     551                 :            :         } else {
     552         [ #  # ]:          0 :                 offset = mon_buff_area_alloc(rp, length + PKT_SIZE + lendesc);
     553                 :            :         }
     554         [ #  # ]:          0 :         if (offset == ~0) {
     555                 :          0 :                 rp->cnt_lost++;
     556                 :          0 :                 spin_unlock_irqrestore(&rp->b_lock, flags);
     557                 :          0 :                 return;
     558                 :            :         }
     559                 :            : 
     560                 :          0 :         ep = MON_OFF2HDR(rp, offset);
     561         [ #  # ]:          0 :         if ((offset += PKT_SIZE) >= rp->b_size) offset = 0;
     562                 :            : 
     563                 :            :         /*
     564                 :            :          * Fill the allocated area.
     565                 :            :          */
     566                 :          0 :         memset(ep, 0, PKT_SIZE);
     567                 :          0 :         ep->type = ev_type;
     568         [ #  # ]:          0 :         ep->xfer_type = xfer_to_pipe[usb_endpoint_type(epd)];
     569         [ #  # ]:          0 :         ep->epnum = dir | usb_endpoint_num(epd);
     570                 :          0 :         ep->devnum = urb->dev->devnum;
     571                 :          0 :         ep->busnum = urb->dev->bus->busnum;
     572                 :          0 :         ep->id = (unsigned long) urb;
     573                 :          0 :         ep->ts_sec = ts.tv_sec;
     574                 :          0 :         ep->ts_usec = ts.tv_nsec / NSEC_PER_USEC;
     575                 :          0 :         ep->status = status;
     576                 :          0 :         ep->len_urb = urb_length;
     577                 :          0 :         ep->len_cap = length + lendesc;
     578                 :          0 :         ep->xfer_flags = urb->transfer_flags;
     579                 :            : 
     580         [ #  # ]:          0 :         if (usb_endpoint_xfer_int(epd)) {
     581                 :          0 :                 ep->interval = urb->interval;
     582         [ #  # ]:          0 :         } else if (usb_endpoint_xfer_isoc(epd)) {
     583                 :          0 :                 ep->interval = urb->interval;
     584                 :          0 :                 ep->start_frame = urb->start_frame;
     585                 :          0 :                 ep->s.iso.error_count = urb->error_count;
     586                 :          0 :                 ep->s.iso.numdesc = urb->number_of_packets;
     587                 :            :         }
     588                 :            : 
     589   [ #  #  #  # ]:          0 :         if (usb_endpoint_xfer_control(epd) && ev_type == 'S') {
     590         [ #  # ]:          0 :                 ep->flag_setup = mon_bin_get_setup(ep->s.setup, urb, ev_type);
     591                 :            :         } else {
     592                 :          0 :                 ep->flag_setup = '-';
     593                 :            :         }
     594                 :            : 
     595         [ #  # ]:          0 :         if (ndesc != 0) {
     596                 :          0 :                 ep->ndesc = ndesc;
     597                 :          0 :                 mon_bin_get_isodesc(rp, offset, urb, ev_type, ndesc);
     598         [ #  # ]:          0 :                 if ((offset += lendesc) >= rp->b_size)
     599                 :          0 :                         offset -= rp->b_size;
     600                 :            :         }
     601                 :            : 
     602         [ #  # ]:          0 :         if (length != 0) {
     603                 :          0 :                 length = mon_bin_get_data(rp, offset, urb, length,
     604                 :            :                                 &ep->flag_data);
     605         [ #  # ]:          0 :                 if (length > 0) {
     606                 :          0 :                         delta = (ep->len_cap + PKT_ALIGN-1) & ~(PKT_ALIGN-1);
     607                 :          0 :                         ep->len_cap -= length;
     608                 :          0 :                         delta -= (ep->len_cap + PKT_ALIGN-1) & ~(PKT_ALIGN-1);
     609         [ #  # ]:          0 :                         mon_buff_area_shrink(rp, delta);
     610                 :            :                 }
     611                 :            :         } else {
     612                 :          0 :                 ep->flag_data = data_tag;
     613                 :            :         }
     614                 :            : 
     615                 :          0 :         spin_unlock_irqrestore(&rp->b_lock, flags);
     616                 :            : 
     617                 :          0 :         wake_up(&rp->b_wait);
     618                 :            : }
     619                 :            : 
     620                 :          0 : static void mon_bin_submit(void *data, struct urb *urb)
     621                 :            : {
     622                 :          0 :         struct mon_reader_bin *rp = data;
     623                 :          0 :         mon_bin_event(rp, urb, 'S', -EINPROGRESS);
     624                 :          0 : }
     625                 :            : 
     626                 :          0 : static void mon_bin_complete(void *data, struct urb *urb, int status)
     627                 :            : {
     628                 :          0 :         struct mon_reader_bin *rp = data;
     629                 :          0 :         mon_bin_event(rp, urb, 'C', status);
     630                 :          0 : }
     631                 :            : 
     632                 :          0 : static void mon_bin_error(void *data, struct urb *urb, int error)
     633                 :            : {
     634                 :          0 :         struct mon_reader_bin *rp = data;
     635                 :          0 :         struct timespec64 ts;
     636                 :          0 :         unsigned long flags;
     637                 :          0 :         unsigned int offset;
     638                 :          0 :         struct mon_bin_hdr *ep;
     639                 :            : 
     640                 :          0 :         ktime_get_real_ts64(&ts);
     641                 :            : 
     642                 :          0 :         spin_lock_irqsave(&rp->b_lock, flags);
     643                 :            : 
     644         [ #  # ]:          0 :         offset = mon_buff_area_alloc(rp, PKT_SIZE);
     645         [ #  # ]:          0 :         if (offset == ~0) {
     646                 :            :                 /* Not incrementing cnt_lost. Just because. */
     647                 :          0 :                 spin_unlock_irqrestore(&rp->b_lock, flags);
     648                 :          0 :                 return;
     649                 :            :         }
     650                 :            : 
     651                 :          0 :         ep = MON_OFF2HDR(rp, offset);
     652                 :            : 
     653                 :          0 :         memset(ep, 0, PKT_SIZE);
     654                 :          0 :         ep->type = 'E';
     655         [ #  # ]:          0 :         ep->xfer_type = xfer_to_pipe[usb_endpoint_type(&urb->ep->desc)];
     656         [ #  # ]:          0 :         ep->epnum = usb_urb_dir_in(urb) ? USB_DIR_IN : 0;
     657                 :          0 :         ep->epnum |= usb_endpoint_num(&urb->ep->desc);
     658                 :          0 :         ep->devnum = urb->dev->devnum;
     659                 :          0 :         ep->busnum = urb->dev->bus->busnum;
     660                 :          0 :         ep->id = (unsigned long) urb;
     661                 :          0 :         ep->ts_sec = ts.tv_sec;
     662                 :          0 :         ep->ts_usec = ts.tv_nsec / NSEC_PER_USEC;
     663                 :          0 :         ep->status = error;
     664                 :            : 
     665                 :          0 :         ep->flag_setup = '-';
     666                 :          0 :         ep->flag_data = 'E';
     667                 :            : 
     668                 :          0 :         spin_unlock_irqrestore(&rp->b_lock, flags);
     669                 :            : 
     670                 :          0 :         wake_up(&rp->b_wait);
     671                 :            : }
     672                 :            : 
     673                 :          0 : static int mon_bin_open(struct inode *inode, struct file *file)
     674                 :            : {
     675                 :          0 :         struct mon_bus *mbus;
     676                 :          0 :         struct mon_reader_bin *rp;
     677                 :          0 :         size_t size;
     678                 :          0 :         int rc;
     679                 :            : 
     680                 :          0 :         mutex_lock(&mon_lock);
     681                 :          0 :         mbus = mon_bus_lookup(iminor(inode));
     682         [ #  # ]:          0 :         if (mbus == NULL) {
     683                 :          0 :                 mutex_unlock(&mon_lock);
     684                 :          0 :                 return -ENODEV;
     685                 :            :         }
     686   [ #  #  #  # ]:          0 :         if (mbus != &mon_bus0 && mbus->u_bus == NULL) {
     687                 :          0 :                 printk(KERN_ERR TAG ": consistency error on open\n");
     688                 :          0 :                 mutex_unlock(&mon_lock);
     689                 :          0 :                 return -ENODEV;
     690                 :            :         }
     691                 :            : 
     692                 :          0 :         rp = kzalloc(sizeof(struct mon_reader_bin), GFP_KERNEL);
     693         [ #  # ]:          0 :         if (rp == NULL) {
     694                 :          0 :                 rc = -ENOMEM;
     695                 :          0 :                 goto err_alloc;
     696                 :            :         }
     697                 :          0 :         spin_lock_init(&rp->b_lock);
     698                 :          0 :         init_waitqueue_head(&rp->b_wait);
     699                 :          0 :         mutex_init(&rp->fetch_lock);
     700                 :          0 :         rp->b_size = BUFF_DFL;
     701                 :            : 
     702                 :          0 :         size = sizeof(struct mon_pgmap) * (rp->b_size/CHUNK_SIZE);
     703         [ #  # ]:          0 :         if ((rp->b_vec = kzalloc(size, GFP_KERNEL)) == NULL) {
     704                 :          0 :                 rc = -ENOMEM;
     705                 :          0 :                 goto err_allocvec;
     706                 :            :         }
     707                 :            : 
     708         [ #  # ]:          0 :         if ((rc = mon_alloc_buff(rp->b_vec, rp->b_size/CHUNK_SIZE)) < 0)
     709                 :          0 :                 goto err_allocbuff;
     710                 :            : 
     711                 :          0 :         rp->r.m_bus = mbus;
     712                 :          0 :         rp->r.r_data = rp;
     713                 :          0 :         rp->r.rnf_submit = mon_bin_submit;
     714                 :          0 :         rp->r.rnf_error = mon_bin_error;
     715                 :          0 :         rp->r.rnf_complete = mon_bin_complete;
     716                 :            : 
     717                 :          0 :         mon_reader_add(mbus, &rp->r);
     718                 :            : 
     719                 :          0 :         file->private_data = rp;
     720                 :          0 :         mutex_unlock(&mon_lock);
     721                 :          0 :         return 0;
     722                 :            : 
     723                 :            : err_allocbuff:
     724                 :          0 :         kfree(rp->b_vec);
     725                 :          0 : err_allocvec:
     726                 :          0 :         kfree(rp);
     727                 :          0 : err_alloc:
     728                 :          0 :         mutex_unlock(&mon_lock);
     729                 :          0 :         return rc;
     730                 :            : }
     731                 :            : 
     732                 :            : /*
     733                 :            :  * Extract an event from buffer and copy it to user space.
     734                 :            :  * Wait if there is no event ready.
     735                 :            :  * Returns zero or error.
     736                 :            :  */
     737                 :          0 : static int mon_bin_get_event(struct file *file, struct mon_reader_bin *rp,
     738                 :            :     struct mon_bin_hdr __user *hdr, unsigned int hdrbytes,
     739                 :            :     void __user *data, unsigned int nbytes)
     740                 :            : {
     741                 :          0 :         unsigned long flags;
     742                 :          0 :         struct mon_bin_hdr *ep;
     743                 :          0 :         size_t step_len;
     744                 :          0 :         unsigned int offset;
     745                 :          0 :         int rc;
     746                 :            : 
     747                 :          0 :         mutex_lock(&rp->fetch_lock);
     748                 :            : 
     749         [ #  # ]:          0 :         if ((rc = mon_bin_wait_event(file, rp)) < 0) {
     750                 :          0 :                 mutex_unlock(&rp->fetch_lock);
     751                 :          0 :                 return rc;
     752                 :            :         }
     753                 :            : 
     754                 :          0 :         ep = MON_OFF2HDR(rp, rp->b_out);
     755                 :            : 
     756   [ #  #  #  # ]:          0 :         if (copy_to_user(hdr, ep, hdrbytes)) {
     757                 :          0 :                 mutex_unlock(&rp->fetch_lock);
     758                 :          0 :                 return -EFAULT;
     759                 :            :         }
     760                 :            : 
     761                 :          0 :         step_len = min(ep->len_cap, nbytes);
     762         [ #  # ]:          0 :         if ((offset = rp->b_out + PKT_SIZE) >= rp->b_size) offset = 0;
     763                 :            : 
     764         [ #  # ]:          0 :         if (copy_from_buf(rp, offset, data, step_len)) {
     765                 :          0 :                 mutex_unlock(&rp->fetch_lock);
     766                 :          0 :                 return -EFAULT;
     767                 :            :         }
     768                 :            : 
     769                 :          0 :         spin_lock_irqsave(&rp->b_lock, flags);
     770         [ #  # ]:          0 :         mon_buff_area_free(rp, PKT_SIZE + ep->len_cap);
     771                 :          0 :         spin_unlock_irqrestore(&rp->b_lock, flags);
     772                 :          0 :         rp->b_read = 0;
     773                 :            : 
     774                 :          0 :         mutex_unlock(&rp->fetch_lock);
     775                 :          0 :         return 0;
     776                 :            : }
     777                 :            : 
     778                 :          0 : static int mon_bin_release(struct inode *inode, struct file *file)
     779                 :            : {
     780                 :          0 :         struct mon_reader_bin *rp = file->private_data;
     781                 :          0 :         struct mon_bus* mbus = rp->r.m_bus;
     782                 :            : 
     783                 :          0 :         mutex_lock(&mon_lock);
     784                 :            : 
     785         [ #  # ]:          0 :         if (mbus->nreaders <= 0) {
     786                 :          0 :                 printk(KERN_ERR TAG ": consistency error on close\n");
     787                 :          0 :                 mutex_unlock(&mon_lock);
     788                 :          0 :                 return 0;
     789                 :            :         }
     790                 :          0 :         mon_reader_del(mbus, &rp->r);
     791                 :            : 
     792                 :          0 :         mon_free_buff(rp->b_vec, rp->b_size/CHUNK_SIZE);
     793                 :          0 :         kfree(rp->b_vec);
     794                 :          0 :         kfree(rp);
     795                 :            : 
     796                 :          0 :         mutex_unlock(&mon_lock);
     797                 :          0 :         return 0;
     798                 :            : }
     799                 :            : 
     800                 :          0 : static ssize_t mon_bin_read(struct file *file, char __user *buf,
     801                 :            :     size_t nbytes, loff_t *ppos)
     802                 :            : {
     803                 :          0 :         struct mon_reader_bin *rp = file->private_data;
     804                 :          0 :         unsigned int hdrbytes = PKT_SZ_API0;
     805                 :          0 :         unsigned long flags;
     806                 :          0 :         struct mon_bin_hdr *ep;
     807                 :          0 :         unsigned int offset;
     808                 :          0 :         size_t step_len;
     809                 :          0 :         char *ptr;
     810                 :          0 :         ssize_t done = 0;
     811                 :          0 :         int rc;
     812                 :            : 
     813                 :          0 :         mutex_lock(&rp->fetch_lock);
     814                 :            : 
     815         [ #  # ]:          0 :         if ((rc = mon_bin_wait_event(file, rp)) < 0) {
     816                 :          0 :                 mutex_unlock(&rp->fetch_lock);
     817                 :          0 :                 return rc;
     818                 :            :         }
     819                 :            : 
     820                 :          0 :         ep = MON_OFF2HDR(rp, rp->b_out);
     821                 :            : 
     822         [ #  # ]:          0 :         if (rp->b_read < hdrbytes) {
     823                 :          0 :                 step_len = min(nbytes, (size_t)(hdrbytes - rp->b_read));
     824                 :          0 :                 ptr = ((char *)ep) + rp->b_read;
     825   [ #  #  #  # ]:          0 :                 if (step_len && copy_to_user(buf, ptr, step_len)) {
     826                 :          0 :                         mutex_unlock(&rp->fetch_lock);
     827                 :          0 :                         return -EFAULT;
     828                 :            :                 }
     829                 :          0 :                 nbytes -= step_len;
     830                 :          0 :                 buf += step_len;
     831                 :          0 :                 rp->b_read += step_len;
     832                 :          0 :                 done += step_len;
     833                 :            :         }
     834                 :            : 
     835         [ #  # ]:          0 :         if (rp->b_read >= hdrbytes) {
     836                 :          0 :                 step_len = ep->len_cap;
     837                 :          0 :                 step_len -= rp->b_read - hdrbytes;
     838                 :          0 :                 if (step_len > nbytes)
     839                 :            :                         step_len = nbytes;
     840                 :          0 :                 offset = rp->b_out + PKT_SIZE;
     841                 :          0 :                 offset += rp->b_read - hdrbytes;
     842         [ #  # ]:          0 :                 if (offset >= rp->b_size)
     843                 :          0 :                         offset -= rp->b_size;
     844         [ #  # ]:          0 :                 if (copy_from_buf(rp, offset, buf, step_len)) {
     845                 :          0 :                         mutex_unlock(&rp->fetch_lock);
     846                 :          0 :                         return -EFAULT;
     847                 :            :                 }
     848                 :          0 :                 nbytes -= step_len;
     849                 :          0 :                 buf += step_len;
     850                 :          0 :                 rp->b_read += step_len;
     851                 :          0 :                 done += step_len;
     852                 :            :         }
     853                 :            : 
     854                 :            :         /*
     855                 :            :          * Check if whole packet was read, and if so, jump to the next one.
     856                 :            :          */
     857         [ #  # ]:          0 :         if (rp->b_read >= hdrbytes + ep->len_cap) {
     858                 :          0 :                 spin_lock_irqsave(&rp->b_lock, flags);
     859         [ #  # ]:          0 :                 mon_buff_area_free(rp, PKT_SIZE + ep->len_cap);
     860                 :          0 :                 spin_unlock_irqrestore(&rp->b_lock, flags);
     861                 :          0 :                 rp->b_read = 0;
     862                 :            :         }
     863                 :            : 
     864                 :          0 :         mutex_unlock(&rp->fetch_lock);
     865                 :          0 :         return done;
     866                 :            : }
     867                 :            : 
     868                 :            : /*
     869                 :            :  * Remove at most nevents from chunked buffer.
     870                 :            :  * Returns the number of removed events.
     871                 :            :  */
     872                 :          0 : static int mon_bin_flush(struct mon_reader_bin *rp, unsigned nevents)
     873                 :            : {
     874                 :          0 :         unsigned long flags;
     875                 :          0 :         struct mon_bin_hdr *ep;
     876                 :          0 :         int i;
     877                 :            : 
     878                 :          0 :         mutex_lock(&rp->fetch_lock);
     879                 :          0 :         spin_lock_irqsave(&rp->b_lock, flags);
     880         [ #  # ]:          0 :         for (i = 0; i < nevents; ++i) {
     881         [ #  # ]:          0 :                 if (MON_RING_EMPTY(rp))
     882                 :            :                         break;
     883                 :            : 
     884                 :          0 :                 ep = MON_OFF2HDR(rp, rp->b_out);
     885         [ #  # ]:          0 :                 mon_buff_area_free(rp, PKT_SIZE + ep->len_cap);
     886                 :            :         }
     887                 :          0 :         spin_unlock_irqrestore(&rp->b_lock, flags);
     888                 :          0 :         rp->b_read = 0;
     889                 :          0 :         mutex_unlock(&rp->fetch_lock);
     890                 :          0 :         return i;
     891                 :            : }
     892                 :            : 
     893                 :            : /*
     894                 :            :  * Fetch at most max event offsets into the buffer and put them into vec.
     895                 :            :  * The events are usually freed later with mon_bin_flush.
     896                 :            :  * Return the effective number of events fetched.
     897                 :            :  */
     898                 :          0 : static int mon_bin_fetch(struct file *file, struct mon_reader_bin *rp,
     899                 :            :     u32 __user *vec, unsigned int max)
     900                 :            : {
     901                 :          0 :         unsigned int cur_out;
     902                 :          0 :         unsigned int bytes, avail;
     903                 :          0 :         unsigned int size;
     904                 :          0 :         unsigned int nevents;
     905                 :          0 :         struct mon_bin_hdr *ep;
     906                 :          0 :         unsigned long flags;
     907                 :          0 :         int rc;
     908                 :            : 
     909                 :          0 :         mutex_lock(&rp->fetch_lock);
     910                 :            : 
     911         [ #  # ]:          0 :         if ((rc = mon_bin_wait_event(file, rp)) < 0) {
     912                 :          0 :                 mutex_unlock(&rp->fetch_lock);
     913                 :          0 :                 return rc;
     914                 :            :         }
     915                 :            : 
     916                 :          0 :         spin_lock_irqsave(&rp->b_lock, flags);
     917                 :          0 :         avail = rp->b_cnt;
     918                 :          0 :         spin_unlock_irqrestore(&rp->b_lock, flags);
     919                 :            : 
     920                 :          0 :         cur_out = rp->b_out;
     921                 :          0 :         nevents = 0;
     922                 :          0 :         bytes = 0;
     923         [ #  # ]:          0 :         while (bytes < avail) {
     924         [ #  # ]:          0 :                 if (nevents >= max)
     925                 :            :                         break;
     926                 :            : 
     927                 :          0 :                 ep = MON_OFF2HDR(rp, cur_out);
     928         [ #  # ]:          0 :                 if (put_user(cur_out, &vec[nevents])) {
     929                 :          0 :                         mutex_unlock(&rp->fetch_lock);
     930                 :          0 :                         return -EFAULT;
     931                 :            :                 }
     932                 :            : 
     933                 :          0 :                 nevents++;
     934                 :          0 :                 size = ep->len_cap + PKT_SIZE;
     935                 :          0 :                 size = (size + PKT_ALIGN-1) & ~(PKT_ALIGN-1);
     936         [ #  # ]:          0 :                 if ((cur_out += size) >= rp->b_size)
     937                 :          0 :                         cur_out -= rp->b_size;
     938                 :          0 :                 bytes += size;
     939                 :            :         }
     940                 :            : 
     941                 :          0 :         mutex_unlock(&rp->fetch_lock);
     942                 :          0 :         return nevents;
     943                 :            : }
     944                 :            : 
     945                 :            : /*
     946                 :            :  * Count events. This is almost the same as the above mon_bin_fetch,
     947                 :            :  * only we do not store offsets into user vector, and we have no limit.
     948                 :            :  */
     949                 :          0 : static int mon_bin_queued(struct mon_reader_bin *rp)
     950                 :            : {
     951                 :          0 :         unsigned int cur_out;
     952                 :          0 :         unsigned int bytes, avail;
     953                 :          0 :         unsigned int size;
     954                 :          0 :         unsigned int nevents;
     955                 :          0 :         struct mon_bin_hdr *ep;
     956                 :          0 :         unsigned long flags;
     957                 :            : 
     958                 :          0 :         mutex_lock(&rp->fetch_lock);
     959                 :            : 
     960                 :          0 :         spin_lock_irqsave(&rp->b_lock, flags);
     961                 :          0 :         avail = rp->b_cnt;
     962                 :          0 :         spin_unlock_irqrestore(&rp->b_lock, flags);
     963                 :            : 
     964                 :          0 :         cur_out = rp->b_out;
     965                 :          0 :         nevents = 0;
     966                 :          0 :         bytes = 0;
     967         [ #  # ]:          0 :         while (bytes < avail) {
     968                 :          0 :                 ep = MON_OFF2HDR(rp, cur_out);
     969                 :            : 
     970                 :          0 :                 nevents++;
     971                 :          0 :                 size = ep->len_cap + PKT_SIZE;
     972                 :          0 :                 size = (size + PKT_ALIGN-1) & ~(PKT_ALIGN-1);
     973         [ #  # ]:          0 :                 if ((cur_out += size) >= rp->b_size)
     974                 :          0 :                         cur_out -= rp->b_size;
     975                 :          0 :                 bytes += size;
     976                 :            :         }
     977                 :            : 
     978                 :          0 :         mutex_unlock(&rp->fetch_lock);
     979                 :          0 :         return nevents;
     980                 :            : }
     981                 :            : 
     982                 :            : /*
     983                 :            :  */
     984                 :          0 : static long mon_bin_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
     985                 :            : {
     986                 :          0 :         struct mon_reader_bin *rp = file->private_data;
     987                 :            :         // struct mon_bus* mbus = rp->r.m_bus;
     988                 :          0 :         int ret = 0;
     989                 :          0 :         struct mon_bin_hdr *ep;
     990                 :          0 :         unsigned long flags;
     991                 :            : 
     992   [ #  #  #  #  :          0 :         switch (cmd) {
             #  #  #  # ]
     993                 :            : 
     994                 :          0 :         case MON_IOCQ_URB_LEN:
     995                 :            :                 /*
     996                 :            :                  * N.B. This only returns the size of data, without the header.
     997                 :            :                  */
     998                 :          0 :                 spin_lock_irqsave(&rp->b_lock, flags);
     999         [ #  # ]:          0 :                 if (!MON_RING_EMPTY(rp)) {
    1000                 :          0 :                         ep = MON_OFF2HDR(rp, rp->b_out);
    1001                 :          0 :                         ret = ep->len_cap;
    1002                 :            :                 }
    1003                 :          0 :                 spin_unlock_irqrestore(&rp->b_lock, flags);
    1004                 :            :                 break;
    1005                 :            : 
    1006                 :          0 :         case MON_IOCQ_RING_SIZE:
    1007                 :          0 :                 mutex_lock(&rp->fetch_lock);
    1008                 :          0 :                 ret = rp->b_size;
    1009                 :          0 :                 mutex_unlock(&rp->fetch_lock);
    1010                 :          0 :                 break;
    1011                 :            : 
    1012                 :          0 :         case MON_IOCT_RING_SIZE:
    1013                 :            :                 /*
    1014                 :            :                  * Changing the buffer size will flush it's contents; the new
    1015                 :            :                  * buffer is allocated before releasing the old one to be sure
    1016                 :            :                  * the device will stay functional also in case of memory
    1017                 :            :                  * pressure.
    1018                 :            :                  */
    1019                 :            :                 {
    1020                 :          0 :                 int size;
    1021                 :          0 :                 struct mon_pgmap *vec;
    1022                 :            : 
    1023         [ #  # ]:          0 :                 if (arg < BUFF_MIN || arg > BUFF_MAX)
    1024                 :            :                         return -EINVAL;
    1025                 :            : 
    1026                 :          0 :                 size = CHUNK_ALIGN(arg);
    1027                 :          0 :                 vec = kcalloc(size / CHUNK_SIZE, sizeof(struct mon_pgmap),
    1028                 :            :                               GFP_KERNEL);
    1029         [ #  # ]:          0 :                 if (vec == NULL) {
    1030                 :            :                         ret = -ENOMEM;
    1031                 :            :                         break;
    1032                 :            :                 }
    1033                 :            : 
    1034                 :          0 :                 ret = mon_alloc_buff(vec, size/CHUNK_SIZE);
    1035         [ #  # ]:          0 :                 if (ret < 0) {
    1036                 :          0 :                         kfree(vec);
    1037                 :          0 :                         break;
    1038                 :            :                 }
    1039                 :            : 
    1040                 :          0 :                 mutex_lock(&rp->fetch_lock);
    1041                 :          0 :                 spin_lock_irqsave(&rp->b_lock, flags);
    1042         [ #  # ]:          0 :                 if (rp->mmap_active) {
    1043                 :            :                         mon_free_buff(vec, size/CHUNK_SIZE);
    1044                 :          0 :                         kfree(vec);
    1045                 :          0 :                         ret = -EBUSY;
    1046                 :            :                 } else {
    1047                 :          0 :                         mon_free_buff(rp->b_vec, rp->b_size/CHUNK_SIZE);
    1048                 :          0 :                         kfree(rp->b_vec);
    1049                 :          0 :                         rp->b_vec  = vec;
    1050                 :          0 :                         rp->b_size = size;
    1051                 :          0 :                         rp->b_read = rp->b_in = rp->b_out = rp->b_cnt = 0;
    1052                 :          0 :                         rp->cnt_lost = 0;
    1053                 :            :                 }
    1054                 :          0 :                 spin_unlock_irqrestore(&rp->b_lock, flags);
    1055                 :          0 :                 mutex_unlock(&rp->fetch_lock);
    1056                 :            :                 }
    1057                 :          0 :                 break;
    1058                 :            : 
    1059                 :          0 :         case MON_IOCH_MFLUSH:
    1060                 :          0 :                 ret = mon_bin_flush(rp, arg);
    1061                 :          0 :                 break;
    1062                 :            : 
    1063                 :          0 :         case MON_IOCX_GET:
    1064                 :            :         case MON_IOCX_GETX:
    1065                 :            :                 {
    1066                 :          0 :                 struct mon_bin_get getb;
    1067                 :            : 
    1068         [ #  # ]:          0 :                 if (copy_from_user(&getb, (void __user *)arg,
    1069                 :            :                                             sizeof(struct mon_bin_get)))
    1070                 :          0 :                         return -EFAULT;
    1071                 :            : 
    1072         [ #  # ]:          0 :                 if (getb.alloc > 0x10000000) /* Want to cast to u32 */
    1073                 :            :                         return -EINVAL;
    1074         [ #  # ]:          0 :                 ret = mon_bin_get_event(file, rp, getb.hdr,
    1075                 :            :                     (cmd == MON_IOCX_GET)? PKT_SZ_API0: PKT_SZ_API1,
    1076                 :            :                     getb.data, (unsigned int)getb.alloc);
    1077                 :            :                 }
    1078                 :          0 :                 break;
    1079                 :            : 
    1080                 :          0 :         case MON_IOCX_MFETCH:
    1081                 :            :                 {
    1082                 :          0 :                 struct mon_bin_mfetch mfetch;
    1083                 :          0 :                 struct mon_bin_mfetch __user *uptr;
    1084                 :            : 
    1085                 :          0 :                 uptr = (struct mon_bin_mfetch __user *)arg;
    1086                 :            : 
    1087         [ #  # ]:          0 :                 if (copy_from_user(&mfetch, uptr, sizeof(mfetch)))
    1088                 :          0 :                         return -EFAULT;
    1089                 :            : 
    1090         [ #  # ]:          0 :                 if (mfetch.nflush) {
    1091                 :          0 :                         ret = mon_bin_flush(rp, mfetch.nflush);
    1092         [ #  # ]:          0 :                         if (ret < 0)
    1093                 :          0 :                                 return ret;
    1094         [ #  # ]:          0 :                         if (put_user(ret, &uptr->nflush))
    1095                 :            :                                 return -EFAULT;
    1096                 :            :                 }
    1097                 :          0 :                 ret = mon_bin_fetch(file, rp, mfetch.offvec, mfetch.nfetch);
    1098         [ #  # ]:          0 :                 if (ret < 0)
    1099                 :          0 :                         return ret;
    1100         [ #  # ]:          0 :                 if (put_user(ret, &uptr->nfetch))
    1101                 :            :                         return -EFAULT;
    1102                 :          0 :                 ret = 0;
    1103                 :            :                 }
    1104                 :          0 :                 break;
    1105                 :            : 
    1106                 :          0 :         case MON_IOCG_STATS: {
    1107                 :          0 :                 struct mon_bin_stats __user *sp;
    1108                 :          0 :                 unsigned int nevents;
    1109                 :          0 :                 unsigned int ndropped;
    1110                 :            : 
    1111                 :          0 :                 spin_lock_irqsave(&rp->b_lock, flags);
    1112                 :          0 :                 ndropped = rp->cnt_lost;
    1113                 :          0 :                 rp->cnt_lost = 0;
    1114                 :          0 :                 spin_unlock_irqrestore(&rp->b_lock, flags);
    1115                 :          0 :                 nevents = mon_bin_queued(rp);
    1116                 :            : 
    1117                 :          0 :                 sp = (struct mon_bin_stats __user *)arg;
    1118         [ #  # ]:          0 :                 if (put_user(ndropped, &sp->dropped))
    1119                 :            :                         return -EFAULT;
    1120         [ #  # ]:          0 :                 if (put_user(nevents, &sp->queued))
    1121                 :            :                         return -EFAULT;
    1122                 :            : 
    1123                 :            :                 }
    1124                 :            :                 break;
    1125                 :            : 
    1126                 :            :         default:
    1127                 :            :                 return -ENOTTY;
    1128                 :            :         }
    1129                 :            : 
    1130                 :          0 :         return ret;
    1131                 :            : }
    1132                 :            : 
    1133                 :            : #ifdef CONFIG_COMPAT
    1134                 :          0 : static long mon_bin_compat_ioctl(struct file *file,
    1135                 :            :     unsigned int cmd, unsigned long arg)
    1136                 :            : {
    1137                 :          0 :         struct mon_reader_bin *rp = file->private_data;
    1138                 :          0 :         int ret;
    1139                 :            : 
    1140   [ #  #  #  #  :          0 :         switch (cmd) {
                      # ]
    1141                 :            : 
    1142                 :          0 :         case MON_IOCX_GET32:
    1143                 :            :         case MON_IOCX_GETX32:
    1144                 :            :                 {
    1145                 :          0 :                 struct mon_bin_get32 getb;
    1146                 :            : 
    1147         [ #  # ]:          0 :                 if (copy_from_user(&getb, (void __user *)arg,
    1148                 :            :                                             sizeof(struct mon_bin_get32)))
    1149                 :          0 :                         return -EFAULT;
    1150                 :            : 
    1151         [ #  # ]:          0 :                 ret = mon_bin_get_event(file, rp, compat_ptr(getb.hdr32),
    1152                 :            :                     (cmd == MON_IOCX_GET32)? PKT_SZ_API0: PKT_SZ_API1,
    1153                 :            :                     compat_ptr(getb.data32), getb.alloc32);
    1154         [ #  # ]:          0 :                 if (ret < 0)
    1155                 :          0 :                         return ret;
    1156                 :            :                 }
    1157                 :          0 :                 return 0;
    1158                 :            : 
    1159                 :          0 :         case MON_IOCX_MFETCH32:
    1160                 :            :                 {
    1161                 :          0 :                 struct mon_bin_mfetch32 mfetch;
    1162                 :          0 :                 struct mon_bin_mfetch32 __user *uptr;
    1163                 :            : 
    1164                 :          0 :                 uptr = (struct mon_bin_mfetch32 __user *) compat_ptr(arg);
    1165                 :            : 
    1166         [ #  # ]:          0 :                 if (copy_from_user(&mfetch, uptr, sizeof(mfetch)))
    1167                 :          0 :                         return -EFAULT;
    1168                 :            : 
    1169         [ #  # ]:          0 :                 if (mfetch.nflush32) {
    1170                 :          0 :                         ret = mon_bin_flush(rp, mfetch.nflush32);
    1171         [ #  # ]:          0 :                         if (ret < 0)
    1172                 :          0 :                                 return ret;
    1173         [ #  # ]:          0 :                         if (put_user(ret, &uptr->nflush32))
    1174                 :            :                                 return -EFAULT;
    1175                 :            :                 }
    1176                 :          0 :                 ret = mon_bin_fetch(file, rp, compat_ptr(mfetch.offvec32),
    1177                 :            :                     mfetch.nfetch32);
    1178         [ #  # ]:          0 :                 if (ret < 0)
    1179                 :          0 :                         return ret;
    1180         [ #  # ]:          0 :                 if (put_user(ret, &uptr->nfetch32))
    1181                 :            :                         return -EFAULT;
    1182                 :            :                 }
    1183                 :          0 :                 return 0;
    1184                 :            : 
    1185                 :          0 :         case MON_IOCG_STATS:
    1186                 :          0 :                 return mon_bin_ioctl(file, cmd, (unsigned long) compat_ptr(arg));
    1187                 :            : 
    1188                 :          0 :         case MON_IOCQ_URB_LEN:
    1189                 :            :         case MON_IOCQ_RING_SIZE:
    1190                 :            :         case MON_IOCT_RING_SIZE:
    1191                 :            :         case MON_IOCH_MFLUSH:
    1192                 :          0 :                 return mon_bin_ioctl(file, cmd, arg);
    1193                 :            : 
    1194                 :            :         default:
    1195                 :            :                 ;
    1196                 :            :         }
    1197                 :            :         return -ENOTTY;
    1198                 :            : }
    1199                 :            : #endif /* CONFIG_COMPAT */
    1200                 :            : 
    1201                 :            : static __poll_t
    1202                 :          0 : mon_bin_poll(struct file *file, struct poll_table_struct *wait)
    1203                 :            : {
    1204                 :          0 :         struct mon_reader_bin *rp = file->private_data;
    1205                 :          0 :         __poll_t mask = 0;
    1206                 :          0 :         unsigned long flags;
    1207                 :            : 
    1208         [ #  # ]:          0 :         if (file->f_mode & FMODE_READ)
    1209         [ #  # ]:          0 :                 poll_wait(file, &rp->b_wait, wait);
    1210                 :            : 
    1211                 :          0 :         spin_lock_irqsave(&rp->b_lock, flags);
    1212         [ #  # ]:          0 :         if (!MON_RING_EMPTY(rp))
    1213                 :          0 :                 mask |= EPOLLIN | EPOLLRDNORM;    /* readable */
    1214                 :          0 :         spin_unlock_irqrestore(&rp->b_lock, flags);
    1215                 :          0 :         return mask;
    1216                 :            : }
    1217                 :            : 
    1218                 :            : /*
    1219                 :            :  * open and close: just keep track of how many times the device is
    1220                 :            :  * mapped, to use the proper memory allocation function.
    1221                 :            :  */
    1222                 :          0 : static void mon_bin_vma_open(struct vm_area_struct *vma)
    1223                 :            : {
    1224                 :          0 :         struct mon_reader_bin *rp = vma->vm_private_data;
    1225                 :          0 :         unsigned long flags;
    1226                 :            : 
    1227                 :          0 :         spin_lock_irqsave(&rp->b_lock, flags);
    1228                 :          0 :         rp->mmap_active++;
    1229                 :          0 :         spin_unlock_irqrestore(&rp->b_lock, flags);
    1230                 :          0 : }
    1231                 :            : 
    1232                 :          0 : static void mon_bin_vma_close(struct vm_area_struct *vma)
    1233                 :            : {
    1234                 :          0 :         unsigned long flags;
    1235                 :            : 
    1236                 :          0 :         struct mon_reader_bin *rp = vma->vm_private_data;
    1237                 :          0 :         spin_lock_irqsave(&rp->b_lock, flags);
    1238                 :          0 :         rp->mmap_active--;
    1239                 :          0 :         spin_unlock_irqrestore(&rp->b_lock, flags);
    1240                 :          0 : }
    1241                 :            : 
    1242                 :            : /*
    1243                 :            :  * Map ring pages to user space.
    1244                 :            :  */
    1245                 :          0 : static vm_fault_t mon_bin_vma_fault(struct vm_fault *vmf)
    1246                 :            : {
    1247                 :          0 :         struct mon_reader_bin *rp = vmf->vma->vm_private_data;
    1248                 :          0 :         unsigned long offset, chunk_idx;
    1249                 :          0 :         struct page *pageptr;
    1250                 :            : 
    1251                 :          0 :         offset = vmf->pgoff << PAGE_SHIFT;
    1252         [ #  # ]:          0 :         if (offset >= rp->b_size)
    1253                 :            :                 return VM_FAULT_SIGBUS;
    1254                 :          0 :         chunk_idx = offset / CHUNK_SIZE;
    1255                 :          0 :         pageptr = rp->b_vec[chunk_idx].pg;
    1256         [ #  # ]:          0 :         get_page(pageptr);
    1257                 :          0 :         vmf->page = pageptr;
    1258                 :          0 :         return 0;
    1259                 :            : }
    1260                 :            : 
    1261                 :            : static const struct vm_operations_struct mon_bin_vm_ops = {
    1262                 :            :         .open =     mon_bin_vma_open,
    1263                 :            :         .close =    mon_bin_vma_close,
    1264                 :            :         .fault =    mon_bin_vma_fault,
    1265                 :            : };
    1266                 :            : 
    1267                 :          0 : static int mon_bin_mmap(struct file *filp, struct vm_area_struct *vma)
    1268                 :            : {
    1269                 :            :         /* don't do anything here: "fault" will set up page table entries */
    1270                 :          0 :         vma->vm_ops = &mon_bin_vm_ops;
    1271                 :          0 :         vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
    1272                 :          0 :         vma->vm_private_data = filp->private_data;
    1273                 :          0 :         mon_bin_vma_open(vma);
    1274                 :          0 :         return 0;
    1275                 :            : }
    1276                 :            : 
    1277                 :            : static const struct file_operations mon_fops_binary = {
    1278                 :            :         .owner =        THIS_MODULE,
    1279                 :            :         .open =         mon_bin_open,
    1280                 :            :         .llseek =       no_llseek,
    1281                 :            :         .read =         mon_bin_read,
    1282                 :            :         /* .write =     mon_text_write, */
    1283                 :            :         .poll =         mon_bin_poll,
    1284                 :            :         .unlocked_ioctl = mon_bin_ioctl,
    1285                 :            : #ifdef CONFIG_COMPAT
    1286                 :            :         .compat_ioctl = mon_bin_compat_ioctl,
    1287                 :            : #endif
    1288                 :            :         .release =      mon_bin_release,
    1289                 :            :         .mmap =         mon_bin_mmap,
    1290                 :            : };
    1291                 :            : 
    1292                 :            : static int mon_bin_wait_event(struct file *file, struct mon_reader_bin *rp)
    1293                 :            : {
    1294                 :            :         DECLARE_WAITQUEUE(waita, current);
    1295                 :            :         unsigned long flags;
    1296                 :            : 
    1297                 :            :         add_wait_queue(&rp->b_wait, &waita);
    1298                 :            :         set_current_state(TASK_INTERRUPTIBLE);
    1299                 :            : 
    1300                 :            :         spin_lock_irqsave(&rp->b_lock, flags);
    1301                 :            :         while (MON_RING_EMPTY(rp)) {
    1302                 :            :                 spin_unlock_irqrestore(&rp->b_lock, flags);
    1303                 :            : 
    1304                 :            :                 if (file->f_flags & O_NONBLOCK) {
    1305                 :            :                         set_current_state(TASK_RUNNING);
    1306                 :            :                         remove_wait_queue(&rp->b_wait, &waita);
    1307                 :            :                         return -EWOULDBLOCK; /* Same as EAGAIN in Linux */
    1308                 :            :                 }
    1309                 :            :                 schedule();
    1310                 :            :                 if (signal_pending(current)) {
    1311                 :            :                         remove_wait_queue(&rp->b_wait, &waita);
    1312                 :            :                         return -EINTR;
    1313                 :            :                 }
    1314                 :            :                 set_current_state(TASK_INTERRUPTIBLE);
    1315                 :            : 
    1316                 :            :                 spin_lock_irqsave(&rp->b_lock, flags);
    1317                 :            :         }
    1318                 :            :         spin_unlock_irqrestore(&rp->b_lock, flags);
    1319                 :            : 
    1320                 :            :         set_current_state(TASK_RUNNING);
    1321                 :            :         remove_wait_queue(&rp->b_wait, &waita);
    1322                 :            :         return 0;
    1323                 :            : }
    1324                 :            : 
    1325                 :          0 : static int mon_alloc_buff(struct mon_pgmap *map, int npages)
    1326                 :            : {
    1327                 :          0 :         int n;
    1328                 :          0 :         unsigned long vaddr;
    1329                 :            : 
    1330         [ #  # ]:          0 :         for (n = 0; n < npages; n++) {
    1331                 :          0 :                 vaddr = get_zeroed_page(GFP_KERNEL);
    1332         [ #  # ]:          0 :                 if (vaddr == 0) {
    1333         [ #  # ]:          0 :                         while (n-- != 0)
    1334                 :          0 :                                 free_page((unsigned long) map[n].ptr);
    1335                 :            :                         return -ENOMEM;
    1336                 :            :                 }
    1337                 :          0 :                 map[n].ptr = (unsigned char *) vaddr;
    1338         [ #  # ]:          0 :                 map[n].pg = virt_to_page((void *) vaddr);
    1339                 :            :         }
    1340                 :            :         return 0;
    1341                 :            : }
    1342                 :            : 
    1343                 :          0 : static void mon_free_buff(struct mon_pgmap *map, int npages)
    1344                 :            : {
    1345                 :          0 :         int n;
    1346                 :            : 
    1347   [ #  #  #  #  :          0 :         for (n = 0; n < npages; n++)
                   #  # ]
    1348                 :          0 :                 free_page((unsigned long) map[n].ptr);
    1349                 :            : }
    1350                 :            : 
    1351                 :         11 : int mon_bin_add(struct mon_bus *mbus, const struct usb_bus *ubus)
    1352                 :            : {
    1353                 :         11 :         struct device *dev;
    1354         [ -  + ]:         11 :         unsigned minor = ubus? ubus->busnum: 0;
    1355                 :            : 
    1356         [ #  # ]:          0 :         if (minor >= MON_BIN_MAX_MINOR)
    1357                 :            :                 return 0;
    1358                 :            : 
    1359                 :         11 :         dev = device_create(mon_bin_class, ubus ? ubus->controller : NULL,
    1360         [ -  + ]:         11 :                             MKDEV(MAJOR(mon_bin_dev0), minor), NULL,
    1361                 :            :                             "usbmon%d", minor);
    1362         [ +  - ]:         11 :         if (IS_ERR(dev))
    1363                 :            :                 return 0;
    1364                 :            : 
    1365                 :         11 :         mbus->classdev = dev;
    1366                 :         11 :         return 1;
    1367                 :            : }
    1368                 :            : 
    1369                 :          0 : void mon_bin_del(struct mon_bus *mbus)
    1370                 :            : {
    1371                 :          0 :         device_destroy(mon_bin_class, mbus->classdev->devt);
    1372                 :          0 : }
    1373                 :            : 
    1374                 :         11 : int __init mon_bin_init(void)
    1375                 :            : {
    1376                 :         11 :         int rc;
    1377                 :            : 
    1378                 :         11 :         mon_bin_class = class_create(THIS_MODULE, "usbmon");
    1379         [ -  + ]:         11 :         if (IS_ERR(mon_bin_class)) {
    1380                 :          0 :                 rc = PTR_ERR(mon_bin_class);
    1381                 :          0 :                 goto err_class;
    1382                 :            :         }
    1383                 :            : 
    1384                 :         11 :         rc = alloc_chrdev_region(&mon_bin_dev0, 0, MON_BIN_MAX_MINOR, "usbmon");
    1385         [ -  + ]:         11 :         if (rc < 0)
    1386                 :          0 :                 goto err_dev;
    1387                 :            : 
    1388                 :         11 :         cdev_init(&mon_bin_cdev, &mon_fops_binary);
    1389                 :         11 :         mon_bin_cdev.owner = THIS_MODULE;
    1390                 :            : 
    1391                 :         11 :         rc = cdev_add(&mon_bin_cdev, mon_bin_dev0, MON_BIN_MAX_MINOR);
    1392         [ -  + ]:         11 :         if (rc < 0)
    1393                 :          0 :                 goto err_add;
    1394                 :            : 
    1395                 :            :         return 0;
    1396                 :            : 
    1397                 :            : err_add:
    1398                 :          0 :         unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR);
    1399                 :          0 : err_dev:
    1400                 :          0 :         class_destroy(mon_bin_class);
    1401                 :            : err_class:
    1402                 :            :         return rc;
    1403                 :            : }
    1404                 :            : 
    1405                 :          0 : void mon_bin_exit(void)
    1406                 :            : {
    1407                 :          0 :         cdev_del(&mon_bin_cdev);
    1408                 :          0 :         unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR);
    1409                 :          0 :         class_destroy(mon_bin_class);
    1410                 :          0 : }

Generated by: LCOV version 1.14