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