diff options
Diffstat (limited to 'drivers/usb/mon/mon_text.c')
| -rw-r--r-- | drivers/usb/mon/mon_text.c | 59 |
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; |
