aboutsummaryrefslogtreecommitdiffstats
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.c30
1 files changed, 24 insertions, 6 deletions
diff --git a/drivers/usb/mon/mon_text.c b/drivers/usb/mon/mon_text.c
index 9f1a9227ebe6..4d0be130f49b 100644
--- a/drivers/usb/mon/mon_text.c
+++ b/drivers/usb/mon/mon_text.c
@@ -7,9 +7,11 @@
7#include <linux/kernel.h> 7#include <linux/kernel.h>
8#include <linux/list.h> 8#include <linux/list.h>
9#include <linux/usb.h> 9#include <linux/usb.h>
10#include <linux/slab.h>
10#include <linux/time.h> 11#include <linux/time.h>
11#include <linux/mutex.h> 12#include <linux/mutex.h>
12#include <linux/debugfs.h> 13#include <linux/debugfs.h>
14#include <linux/scatterlist.h>
13#include <asm/uaccess.h> 15#include <asm/uaccess.h>
14 16
15#include "usb_mon.h" 17#include "usb_mon.h"
@@ -137,6 +139,8 @@ static inline char mon_text_get_setup(struct mon_event_text *ep,
137static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb, 139static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
138 int len, char ev_type, struct mon_bus *mbus) 140 int len, char ev_type, struct mon_bus *mbus)
139{ 141{
142 void *src;
143
140 if (len <= 0) 144 if (len <= 0)
141 return 'L'; 145 return 'L';
142 if (len >= DATA_MAX) 146 if (len >= DATA_MAX)
@@ -150,10 +154,24 @@ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb,
150 return '>'; 154 return '>';
151 } 155 }
152 156
153 if (urb->transfer_buffer == NULL) 157 if (urb->num_sgs == 0) {
154 return 'Z'; /* '0' would be not as pretty. */ 158 src = urb->transfer_buffer;
159 if (src == NULL)
160 return 'Z'; /* '0' would be not as pretty. */
161 } else {
162 struct scatterlist *sg = urb->sg->sg;
163
164 /* If IOMMU coalescing occurred, we cannot trust sg_page */
165 if (urb->sg->nents != urb->num_sgs ||
166 PageHighMem(sg_page(sg)))
167 return 'D';
155 168
156 memcpy(ep->data, urb->transfer_buffer, len); 169 /* For the text interface we copy only the first sg buffer */
170 len = min_t(int, sg->length, len);
171 src = sg_virt(sg);
172 }
173
174 memcpy(ep->data, src, len);
157 return 0; 175 return 0;
158} 176}
159 177
@@ -163,7 +181,7 @@ static inline unsigned int mon_get_timestamp(void)
163 unsigned int stamp; 181 unsigned int stamp;
164 182
165 do_gettimeofday(&tval); 183 do_gettimeofday(&tval);
166 stamp = tval.tv_sec & 0xFFFF; /* 2^32 = 4294967296. Limit to 4096s. */ 184 stamp = tval.tv_sec & 0xFFF; /* 2^32 = 4294967296. Limit to 4096s. */
167 stamp = stamp * 1000000 + tval.tv_usec; 185 stamp = stamp * 1000000 + tval.tv_usec;
168 return stamp; 186 return stamp;
169} 187}
@@ -256,12 +274,12 @@ static void mon_text_error(void *data, struct urb *urb, int error)
256 274
257 ep->type = 'E'; 275 ep->type = 'E';
258 ep->id = (unsigned long) urb; 276 ep->id = (unsigned long) urb;
259 ep->busnum = 0; 277 ep->busnum = urb->dev->bus->busnum;
260 ep->devnum = urb->dev->devnum; 278 ep->devnum = urb->dev->devnum;
261 ep->epnum = usb_endpoint_num(&urb->ep->desc); 279 ep->epnum = usb_endpoint_num(&urb->ep->desc);
262 ep->xfertype = usb_endpoint_type(&urb->ep->desc); 280 ep->xfertype = usb_endpoint_type(&urb->ep->desc);
263 ep->is_in = usb_urb_dir_in(urb); 281 ep->is_in = usb_urb_dir_in(urb);
264 ep->tstamp = 0; 282 ep->tstamp = mon_get_timestamp();
265 ep->length = 0; 283 ep->length = 0;
266 ep->status = error; 284 ep->status = error;
267 285