aboutsummaryrefslogtreecommitdiff
path: root/drivers/usb/mon/mon_text.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/mon/mon_text.c')
-rw-r--r--drivers/usb/mon/mon_text.c59
1 files changed, 34 insertions, 25 deletions
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index 5e3e4e9b6c7..ad408251d95 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -7,9 +7,12 @@
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/usb.h>
+#include <linux/slab.h>
#include <linux/time.h>
+#include <linux/export.h>
#include <linux/mutex.h>
#include <linux/debugfs.h>
+#include <linux/scatterlist.h>
#include <asm/uaccess.h>
#include "usb_mon.h"
@@ -87,7 +90,7 @@ struct mon_reader_text {
static struct dentry *mon_dir; /* Usually /sys/kernel/debug/usbmon */
-static void mon_text_ctor(struct kmem_cache *, void *);
+static void mon_text_ctor(void *);
struct mon_text_ptr {
int cnt, limit;
@@ -137,6 +140,8 @@ static inline char mon_text_get_setup(struct mon_event_text *ep,
static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
int len, char ev_type, struct mon_bus *mbus)
{
+ void *src;
+
if (len <= 0)
return 'L';
if (len >= DATA_MAX)
@@ -150,24 +155,22 @@ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
return '>';
}
- /*
- * The check to see if it's safe to poke at data has an enormous
- * number of corner cases, but it seems that the following is
- * more or less safe.
- *
- * We do not even try to look at transfer_buffer, because it can
- * contain non-NULL garbage in case the upper level promised to
- * set DMA for the HCD.
- */
- if (urb->dev->bus->uses_dma &&
- (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
- return mon_dmapeek(ep->data, urb->transfer_dma, len);
- }
+ if (urb->num_sgs == 0) {
+ src = urb->transfer_buffer;
+ if (src == NULL)
+ return 'Z'; /* '0' would be not as pretty. */
+ } else {
+ struct scatterlist *sg = urb->sg;
- if (urb->transfer_buffer == NULL)
- return 'Z'; /* '0' would be not as pretty. */
+ if (PageHighMem(sg_page(sg)))
+ return 'D';
- memcpy(ep->data, urb->transfer_buffer, len);
+ /* For the text interface we copy only the first sg buffer */
+ len = min_t(int, sg->length, len);
+ src = sg_virt(sg);
+ }
+
+ memcpy(ep->data, src, len);
return 0;
}
@@ -177,7 +180,7 @@ static inline unsigned int mon_get_timestamp(void)
unsigned int stamp;
do_gettimeofday(&tval);
- stamp = tval.tv_sec & 0xFFFF; /* 2^32 = 4294967296. Limit to 4096s. */
+ stamp = tval.tv_sec & 0xFFF; /* 2^32 = 4294967296. Limit to 4096s. */
stamp = stamp * 1000000 + tval.tv_usec;
return stamp;
}
@@ -234,6 +237,9 @@ static void mon_text_event(struct mon_reader_text *rp, struct urb *urb,
fp++;
dp++;
}
+ /* Wasteful, but simple to understand: ISO 'C' is sparse. */
+ if (ev_type == 'C')
+ ep->length = urb->transfer_buffer_length;
}
ep->setup_flag = mon_text_get_setup(ep, urb, ev_type, rp->r.m_bus);
@@ -270,12 +276,12 @@ static void mon_text_error(void *data, struct urb *urb, int error)
ep->type = 'E';
ep->id = (unsigned long) urb;
- ep->busnum = 0;
+ ep->busnum = urb->dev->bus->busnum;
ep->devnum = urb->dev->devnum;
ep->epnum = usb_endpoint_num(&urb->ep->desc);
ep->xfertype = usb_endpoint_type(&urb->ep->desc);
ep->is_in = usb_urb_dir_in(urb);
- ep->tstamp = 0;
+ ep->tstamp = mon_get_timestamp();
ep->length = 0;
ep->status = error;
@@ -665,6 +671,9 @@ int mon_text_add(struct mon_bus *mbus, const struct usb_bus *ubus)
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)
@@ -720,7 +729,7 @@ void mon_text_del(struct mon_bus *mbus)
/*
* Slab interface: constructor.
*/
-static void mon_text_ctor(struct kmem_cache *slab, void *mem)
+static void mon_text_ctor(void *mem)
{
/*
* Nothing to initialize. No, really!
@@ -733,14 +742,14 @@ int __init mon_text_init(void)
{
struct dentry *mondir;
- mondir = debugfs_create_dir("usbmon", NULL);
+ mondir = debugfs_create_dir("usbmon", usb_debug_root);
if (IS_ERR(mondir)) {
- printk(KERN_NOTICE TAG ": debugfs is not available\n");
- return -ENODEV;
+ /* debugfs not available, but we can use usbmon without it */
+ return 0;
}
if (mondir == NULL) {
printk(KERN_NOTICE TAG ": unable to create usbmon directory\n");
- return -ENODEV;
+ return -ENOMEM;
}
mon_dir = mondir;
return 0;