summaryrefslogtreecommitdiff
path: root/drivers/usb/mon
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/mon')
-rw-r--r--drivers/usb/mon/Kconfig3
-rw-r--r--drivers/usb/mon/mon_bin.c75
-rw-r--r--drivers/usb/mon/mon_main.c24
-rw-r--r--drivers/usb/mon/mon_stat.c7
-rw-r--r--drivers/usb/mon/mon_text.c66
5 files changed, 82 insertions, 93 deletions
diff --git a/drivers/usb/mon/Kconfig b/drivers/usb/mon/Kconfig
index 5c6ffa2a612e..ffc7cd422874 100644
--- a/drivers/usb/mon/Kconfig
+++ b/drivers/usb/mon/Kconfig
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
#
# USB Monitor configuration
#
@@ -7,6 +8,6 @@ config USB_MON
help
If you select this option, a component which captures the USB traffic
between peripheral-specific drivers and HC drivers will be built.
- For more information, see <file:Documentation/usb/usbmon.txt>.
+ For more information, see <file:Documentation/usb/usbmon.rst>.
If unsure, say Y, if allowed, otherwise M.
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index ac2b4fcc265f..e713fc5964b1 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -68,18 +68,20 @@
* The magic limit was calculated so that it allows the monitoring
* application to pick data once in two ticks. This way, another application,
* which presumably drives the bus, gets to hog CPU, yet we collect our data.
- * If HZ is 100, a 480 mbit/s bus drives 614 KB every jiffy. USB has an
- * enormous overhead built into the bus protocol, so we need about 1000 KB.
+ *
+ * Originally, for a 480 Mbit/s bus this required a buffer of about 1 MB. For
+ * modern 20 Gbps buses, this value increases to over 50 MB. The maximum
+ * buffer size is set to 64 MiB to accommodate this.
*
* This is still too much for most cases, where we just snoop a few
* descriptor fetches for enumeration. So, the default is a "reasonable"
- * amount for systems with HZ=250 and incomplete bus saturation.
+ * amount for typical, low-throughput use cases.
*
* XXX What about multi-megabyte URBs which take minutes to transfer?
*/
-#define BUFF_MAX CHUNK_ALIGN(1200*1024)
-#define BUFF_DFL CHUNK_ALIGN(300*1024)
-#define BUFF_MIN CHUNK_ALIGN(8*1024)
+#define BUFF_MAX CHUNK_ALIGN(64*1024*1024)
+#define BUFF_DFL CHUNK_ALIGN(300*1024)
+#define BUFF_MIN CHUNK_ALIGN(8*1024)
/*
* The per-event API header (2 per URB).
@@ -213,7 +215,10 @@ static unsigned char xfer_to_pipe[4] = {
PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
};
-static struct class *mon_bin_class;
+static const struct class mon_bin_class = {
+ .name = "usbmon",
+};
+
static dev_t mon_bin_dev0;
static struct cdev mon_bin_cdev;
@@ -820,7 +825,7 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf,
ep = MON_OFF2HDR(rp, rp->b_out);
if (rp->b_read < hdrbytes) {
- step_len = min(nbytes, (size_t)(hdrbytes - rp->b_read));
+ step_len = min_t(size_t, nbytes, hdrbytes - rp->b_read);
ptr = ((char *)ep) + rp->b_read;
if (step_len && copy_to_user(buf, ptr, step_len)) {
mutex_unlock(&rp->fetch_lock);
@@ -1039,12 +1044,18 @@ static long mon_bin_ioctl(struct file *file, unsigned int cmd, unsigned long arg
mutex_lock(&rp->fetch_lock);
spin_lock_irqsave(&rp->b_lock, flags);
- mon_free_buff(rp->b_vec, rp->b_size/CHUNK_SIZE);
- kfree(rp->b_vec);
- rp->b_vec = vec;
- rp->b_size = size;
- rp->b_read = rp->b_in = rp->b_out = rp->b_cnt = 0;
- rp->cnt_lost = 0;
+ if (rp->mmap_active) {
+ mon_free_buff(vec, size/CHUNK_SIZE);
+ kfree(vec);
+ ret = -EBUSY;
+ } else {
+ mon_free_buff(rp->b_vec, rp->b_size/CHUNK_SIZE);
+ kfree(rp->b_vec);
+ rp->b_vec = vec;
+ rp->b_size = size;
+ rp->b_read = rp->b_in = rp->b_out = rp->b_cnt = 0;
+ rp->cnt_lost = 0;
+ }
spin_unlock_irqrestore(&rp->b_lock, flags);
mutex_unlock(&rp->fetch_lock);
}
@@ -1216,13 +1227,21 @@ mon_bin_poll(struct file *file, struct poll_table_struct *wait)
static void mon_bin_vma_open(struct vm_area_struct *vma)
{
struct mon_reader_bin *rp = vma->vm_private_data;
+ unsigned long flags;
+
+ spin_lock_irqsave(&rp->b_lock, flags);
rp->mmap_active++;
+ spin_unlock_irqrestore(&rp->b_lock, flags);
}
static void mon_bin_vma_close(struct vm_area_struct *vma)
{
+ unsigned long flags;
+
struct mon_reader_bin *rp = vma->vm_private_data;
+ spin_lock_irqsave(&rp->b_lock, flags);
rp->mmap_active--;
+ spin_unlock_irqrestore(&rp->b_lock, flags);
}
/*
@@ -1233,18 +1252,19 @@ static vm_fault_t mon_bin_vma_fault(struct vm_fault *vmf)
struct mon_reader_bin *rp = vmf->vma->vm_private_data;
unsigned long offset, chunk_idx;
struct page *pageptr;
+ unsigned long flags;
- mutex_lock(&rp->fetch_lock);
+ spin_lock_irqsave(&rp->b_lock, flags);
offset = vmf->pgoff << PAGE_SHIFT;
if (offset >= rp->b_size) {
- mutex_unlock(&rp->fetch_lock);
+ spin_unlock_irqrestore(&rp->b_lock, flags);
return VM_FAULT_SIGBUS;
}
chunk_idx = offset / CHUNK_SIZE;
pageptr = rp->b_vec[chunk_idx].pg;
get_page(pageptr);
- mutex_unlock(&rp->fetch_lock);
vmf->page = pageptr;
+ spin_unlock_irqrestore(&rp->b_lock, flags);
return 0;
}
@@ -1258,7 +1278,11 @@ static int mon_bin_mmap(struct file *filp, struct vm_area_struct *vma)
{
/* don't do anything here: "fault" will set up page table entries */
vma->vm_ops = &mon_bin_vm_ops;
- vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
+
+ if (vma->vm_flags & VM_WRITE)
+ return -EPERM;
+
+ vm_flags_mod(vma, VM_DONTEXPAND | VM_DONTDUMP, VM_MAYWRITE);
vma->vm_private_data = filp->private_data;
mon_bin_vma_open(vma);
return 0;
@@ -1267,7 +1291,6 @@ static int mon_bin_mmap(struct file *filp, struct vm_area_struct *vma)
static const struct file_operations mon_fops_binary = {
.owner = THIS_MODULE,
.open = mon_bin_open,
- .llseek = no_llseek,
.read = mon_bin_read,
/* .write = mon_text_write, */
.poll = mon_bin_poll,
@@ -1346,7 +1369,7 @@ int mon_bin_add(struct mon_bus *mbus, const struct usb_bus *ubus)
if (minor >= MON_BIN_MAX_MINOR)
return 0;
- dev = device_create(mon_bin_class, ubus ? ubus->controller : NULL,
+ dev = device_create(&mon_bin_class, ubus ? ubus->controller : NULL,
MKDEV(MAJOR(mon_bin_dev0), minor), NULL,
"usbmon%d", minor);
if (IS_ERR(dev))
@@ -1358,18 +1381,16 @@ int mon_bin_add(struct mon_bus *mbus, const struct usb_bus *ubus)
void mon_bin_del(struct mon_bus *mbus)
{
- device_destroy(mon_bin_class, mbus->classdev->devt);
+ device_destroy(&mon_bin_class, mbus->classdev->devt);
}
int __init mon_bin_init(void)
{
int rc;
- mon_bin_class = class_create(THIS_MODULE, "usbmon");
- if (IS_ERR(mon_bin_class)) {
- rc = PTR_ERR(mon_bin_class);
+ rc = class_register(&mon_bin_class);
+ if (rc)
goto err_class;
- }
rc = alloc_chrdev_region(&mon_bin_dev0, 0, MON_BIN_MAX_MINOR, "usbmon");
if (rc < 0)
@@ -1387,7 +1408,7 @@ int __init mon_bin_init(void)
err_add:
unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR);
err_dev:
- class_destroy(mon_bin_class);
+ class_unregister(&mon_bin_class);
err_class:
return rc;
}
@@ -1396,5 +1417,5 @@ void mon_bin_exit(void)
{
cdev_del(&mon_bin_cdev);
unregister_chrdev_region(mon_bin_dev0, MON_BIN_MAX_MINOR);
- class_destroy(mon_bin_class);
+ class_unregister(&mon_bin_class);
}
diff --git a/drivers/usb/mon/mon_main.c b/drivers/usb/mon/mon_main.c
index 9812d102a005..af852d53aac6 100644
--- a/drivers/usb/mon/mon_main.c
+++ b/drivers/usb/mon/mon_main.c
@@ -81,15 +81,12 @@ void mon_reader_del(struct mon_bus *mbus, struct mon_reader *r)
static void mon_bus_submit(struct mon_bus *mbus, struct urb *urb)
{
unsigned long flags;
- struct list_head *pos;
struct mon_reader *r;
spin_lock_irqsave(&mbus->lock, flags);
mbus->cnt_events++;
- list_for_each (pos, &mbus->r_list) {
- r = list_entry(pos, struct mon_reader, r_link);
+ list_for_each_entry(r, &mbus->r_list, r_link)
r->rnf_submit(r->r_data, urb);
- }
spin_unlock_irqrestore(&mbus->lock, flags);
}
@@ -108,15 +105,12 @@ static void mon_submit(struct usb_bus *ubus, struct urb *urb)
static void mon_bus_submit_error(struct mon_bus *mbus, struct urb *urb, int error)
{
unsigned long flags;
- struct list_head *pos;
struct mon_reader *r;
spin_lock_irqsave(&mbus->lock, flags);
mbus->cnt_events++;
- list_for_each (pos, &mbus->r_list) {
- r = list_entry(pos, struct mon_reader, r_link);
+ list_for_each_entry(r, &mbus->r_list, r_link)
r->rnf_error(r->r_data, urb, error);
- }
spin_unlock_irqrestore(&mbus->lock, flags);
}
@@ -135,15 +129,12 @@ static void mon_submit_error(struct usb_bus *ubus, struct urb *urb, int error)
static void mon_bus_complete(struct mon_bus *mbus, struct urb *urb, int status)
{
unsigned long flags;
- struct list_head *pos;
struct mon_reader *r;
spin_lock_irqsave(&mbus->lock, flags);
mbus->cnt_events++;
- list_for_each (pos, &mbus->r_list) {
- r = list_entry(pos, struct mon_reader, r_link);
+ list_for_each_entry(r, &mbus->r_list, r_link)
r->rnf_complete(r->r_data, urb, status);
- }
spin_unlock_irqrestore(&mbus->lock, flags);
}
@@ -165,11 +156,9 @@ static void mon_complete(struct usb_bus *ubus, struct urb *urb, int status)
static void mon_stop(struct mon_bus *mbus)
{
struct usb_bus *ubus;
- struct list_head *p;
if (mbus == &mon_bus0) {
- list_for_each (p, &mon_buses) {
- mbus = list_entry(p, struct mon_bus, bus_link);
+ list_for_each_entry(mbus, &mon_buses, bus_link) {
/*
* We do not change nreaders here, so rely on mon_lock.
*/
@@ -332,14 +321,12 @@ static void mon_bus0_init(void)
*/
struct mon_bus *mon_bus_lookup(unsigned int num)
{
- struct list_head *p;
struct mon_bus *mbus;
if (num == 0) {
return &mon_bus0;
}
- list_for_each (p, &mon_buses) {
- mbus = list_entry(p, struct mon_bus, bus_link);
+ list_for_each_entry(mbus, &mon_buses, bus_link) {
if (mbus->u_bus->busnum == num) {
return mbus;
}
@@ -432,4 +419,5 @@ static void __exit mon_exit(void)
module_init(mon_init);
module_exit(mon_exit);
+MODULE_DESCRIPTION("USB Monitor");
MODULE_LICENSE("GPL");
diff --git a/drivers/usb/mon/mon_stat.c b/drivers/usb/mon/mon_stat.c
index 98ab0cc473d6..398e02af6a2b 100644
--- a/drivers/usb/mon/mon_stat.c
+++ b/drivers/usb/mon/mon_stat.c
@@ -35,9 +35,9 @@ static int mon_stat_open(struct inode *inode, struct file *file)
mbus = inode->i_private;
- sp->slen = snprintf(sp->str, STAT_BUF_SIZE,
- "nreaders %d events %u text_lost %u\n",
- mbus->nreaders, mbus->cnt_events, mbus->cnt_text_lost);
+ sp->slen = scnprintf(sp->str, STAT_BUF_SIZE,
+ "nreaders %d events %u text_lost %u\n",
+ mbus->nreaders, mbus->cnt_events, mbus->cnt_text_lost);
file->private_data = sp;
return 0;
@@ -62,7 +62,6 @@ static int mon_stat_release(struct inode *inode, struct file *file)
const struct file_operations mon_fops_stat = {
.owner = THIS_MODULE,
.open = mon_stat_open,
- .llseek = no_llseek,
.read = mon_stat_read,
/* .write = mon_stat_write, */
/* .poll = mon_stat_poll, */
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index bc5ecd5ff565..68b9b2b41189 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -352,7 +352,7 @@ static int mon_text_open(struct inode *inode, struct file *file)
rp->r.rnf_error = mon_text_error;
rp->r.rnf_complete = mon_text_complete;
- snprintf(rp->slab_name, SLAB_NAME_SZ, "mon_text_%p", rp);
+ scnprintf(rp->slab_name, SLAB_NAME_SZ, "mon_text_%p", rp);
rp->e_slab = kmem_cache_create(rp->slab_name,
sizeof(struct mon_event_text), sizeof(long), 0,
mon_text_ctor);
@@ -414,7 +414,7 @@ static ssize_t mon_text_read_t(struct file *file, char __user *buf,
mon_text_read_head_t(rp, &ptr, ep);
mon_text_read_statset(rp, &ptr, ep);
- ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt,
+ ptr.cnt += scnprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt,
" %d", ep->length);
mon_text_read_data(rp, &ptr, ep);
@@ -462,7 +462,7 @@ static ssize_t mon_text_read_u(struct file *file, char __user *buf,
} else {
mon_text_read_statset(rp, &ptr, ep);
}
- ptr.cnt += snprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt,
+ ptr.cnt += scnprintf(ptr.pbuf + ptr.cnt, ptr.limit - ptr.cnt,
" %d", ep->length);
mon_text_read_data(rp, &ptr, ep);
@@ -520,7 +520,7 @@ static void mon_text_read_head_t(struct mon_reader_text *rp,
case USB_ENDPOINT_XFER_CONTROL: utype = 'C'; break;
default: /* PIPE_BULK */ utype = 'B';
}
- p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+ p->cnt += scnprintf(p->pbuf + p->cnt, p->limit - p->cnt,
"%lx %u %c %c%c:%03u:%02u",
ep->id, ep->tstamp, ep->type,
utype, udir, ep->devnum, ep->epnum);
@@ -538,7 +538,7 @@ static void mon_text_read_head_u(struct mon_reader_text *rp,
case USB_ENDPOINT_XFER_CONTROL: utype = 'C'; break;
default: /* PIPE_BULK */ utype = 'B';
}
- p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+ p->cnt += scnprintf(p->pbuf + p->cnt, p->limit - p->cnt,
"%lx %u %c %c%c:%d:%03u:%u",
ep->id, ep->tstamp, ep->type,
utype, udir, ep->busnum, ep->devnum, ep->epnum);
@@ -549,7 +549,7 @@ static void mon_text_read_statset(struct mon_reader_text *rp,
{
if (ep->setup_flag == 0) { /* Setup packet is present and captured */
- p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+ p->cnt += scnprintf(p->pbuf + p->cnt, p->limit - p->cnt,
" s %02x %02x %04x %04x %04x",
ep->setup[0],
ep->setup[1],
@@ -557,10 +557,10 @@ static void mon_text_read_statset(struct mon_reader_text *rp,
(ep->setup[5] << 8) | ep->setup[4],
(ep->setup[7] << 8) | ep->setup[6]);
} else if (ep->setup_flag != '-') { /* Unable to capture setup packet */
- p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+ p->cnt += scnprintf(p->pbuf + p->cnt, p->limit - p->cnt,
" %c __ __ ____ ____ ____", ep->setup_flag);
} else { /* No setup for this kind of URB */
- p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+ p->cnt += scnprintf(p->pbuf + p->cnt, p->limit - p->cnt,
" %d", ep->status);
}
}
@@ -568,7 +568,7 @@ static void mon_text_read_statset(struct mon_reader_text *rp,
static void mon_text_read_intstat(struct mon_reader_text *rp,
struct mon_text_ptr *p, const struct mon_event_text *ep)
{
- p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+ p->cnt += scnprintf(p->pbuf + p->cnt, p->limit - p->cnt,
" %d:%d", ep->status, ep->interval);
}
@@ -576,10 +576,10 @@ static void mon_text_read_isostat(struct mon_reader_text *rp,
struct mon_text_ptr *p, const struct mon_event_text *ep)
{
if (ep->type == 'S') {
- p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+ p->cnt += scnprintf(p->pbuf + p->cnt, p->limit - p->cnt,
" %d:%d:%d", ep->status, ep->interval, ep->start_frame);
} else {
- p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+ p->cnt += scnprintf(p->pbuf + p->cnt, p->limit - p->cnt,
" %d:%d:%d:%d",
ep->status, ep->interval, ep->start_frame, ep->error_count);
}
@@ -592,7 +592,7 @@ static void mon_text_read_isodesc(struct mon_reader_text *rp,
int i;
const struct mon_iso_desc *dp;
- p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+ p->cnt += scnprintf(p->pbuf + p->cnt, p->limit - p->cnt,
" %d", ep->numdesc);
ndesc = ep->numdesc;
if (ndesc > ISODESC_MAX)
@@ -601,7 +601,7 @@ static void mon_text_read_isodesc(struct mon_reader_text *rp,
ndesc = 0;
dp = ep->isodesc;
for (i = 0; i < ndesc; i++) {
- p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+ p->cnt += scnprintf(p->pbuf + p->cnt, p->limit - p->cnt,
" %d:%u:%u", dp->status, dp->offset, dp->length);
dp++;
}
@@ -614,28 +614,28 @@ static void mon_text_read_data(struct mon_reader_text *rp,
if ((data_len = ep->length) > 0) {
if (ep->data_flag == 0) {
- p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+ p->cnt += scnprintf(p->pbuf + p->cnt, p->limit - p->cnt,
" =");
if (data_len >= DATA_MAX)
data_len = DATA_MAX;
for (i = 0; i < data_len; i++) {
if (i % 4 == 0) {
- p->cnt += snprintf(p->pbuf + p->cnt,
+ p->cnt += scnprintf(p->pbuf + p->cnt,
p->limit - p->cnt,
" ");
}
- p->cnt += snprintf(p->pbuf + p->cnt,
+ p->cnt += scnprintf(p->pbuf + p->cnt,
p->limit - p->cnt,
"%02x", ep->data[i]);
}
- p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+ p->cnt += scnprintf(p->pbuf + p->cnt, p->limit - p->cnt,
"\n");
} else {
- p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt,
+ p->cnt += scnprintf(p->pbuf + p->cnt, p->limit - p->cnt,
" %c\n", ep->data_flag);
}
} else {
- p->cnt += snprintf(p->pbuf + p->cnt, p->limit - p->cnt, "\n");
+ p->cnt += scnprintf(p->pbuf + p->cnt, p->limit - p->cnt, "\n");
}
}
@@ -685,7 +685,6 @@ static int mon_text_release(struct inode *inode, struct file *file)
static const struct file_operations mon_fops_text_t = {
.owner = THIS_MODULE,
.open = mon_text_open,
- .llseek = no_llseek,
.read = mon_text_read_t,
.release = mon_text_release,
};
@@ -693,53 +692,34 @@ static const struct file_operations mon_fops_text_t = {
static const struct file_operations mon_fops_text_u = {
.owner = THIS_MODULE,
.open = mon_text_open,
- .llseek = no_llseek,
.read = mon_text_read_u,
.release = mon_text_release,
};
int mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus)
{
- enum { NAMESZ = 10 };
+ enum { NAMESZ = 12 };
char name[NAMESZ];
int busnum = ubus? ubus->busnum: 0;
- int rc;
if (mon_dir == NULL)
return 0;
if (ubus != NULL) {
- rc = snprintf(name, NAMESZ, "%dt", busnum);
- if (rc <= 0 || rc >= NAMESZ)
- goto err_print_t;
+ scnprintf(name, NAMESZ, "%dt", busnum);
mbus->dent_t = debugfs_create_file(name, 0600, mon_dir, mbus,
&mon_fops_text_t);
}
- rc = snprintf(name, NAMESZ, "%du", busnum);
- if (rc <= 0 || rc >= NAMESZ)
- goto err_print_u;
+ scnprintf(name, NAMESZ, "%du", busnum);
mbus->dent_u = debugfs_create_file(name, 0600, mon_dir, mbus,
&mon_fops_text_u);
- rc = snprintf(name, NAMESZ, "%ds", busnum);
- if (rc <= 0 || rc >= NAMESZ)
- goto err_print_s;
+ scnprintf(name, NAMESZ, "%ds", busnum);
mbus->dent_s = debugfs_create_file(name, 0600, mon_dir, mbus,
&mon_fops_stat);
return 1;
-
-err_print_s:
- debugfs_remove(mbus->dent_u);
- mbus->dent_u = NULL;
-err_print_u:
- if (ubus != NULL) {
- debugfs_remove(mbus->dent_t);
- mbus->dent_t = NULL;
- }
-err_print_t:
- return 0;
}
void mon_text_del(struct mon_bus *mbus)