diff options
author | Martin Fuzzey <mfuzzey@gmail.com> | 2011-01-16 13:17:11 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-01-22 22:42:13 -0500 |
commit | 084fb206a91f72b22c4e2f41709730a81e3e0de6 (patch) | |
tree | 91c015766ad21448b8f26dd36fbda9db6fb334d4 /drivers/usb/misc/usbtest.c | |
parent | 50a6cb932d5cccc6a165219f137b87ea596b4cd0 (diff) |
USB: usbtest - Add tests to ensure HCDs can accept byte aligned buffers.
Add a set of new tests similar to the existing ones but using
transfer buffers at an "odd" address [ie offset of +1 from
the buffer obtained by kmalloc() or usb_alloc_coherent()]
The new tests are:
#17 : bulk out (like #1) using kmalloc and DMA mapping by USB core.
#18 : bulk in (like #2) using kmalloc and DMA mapping by USB core.
#19 : bulk out (like #1) using usb_alloc_coherent()
#20 : bulk in (like #2) using usb_alloc_coherent()
#21 : control write (like #14)
#22 : isochonous out (like #15)
#23 : isochonous in (like #16)
Signed-off-by: Martin Fuzzey <mfuzzey@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/misc/usbtest.c')
-rw-r--r-- | drivers/usb/misc/usbtest.c | 236 |
1 files changed, 212 insertions, 24 deletions
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index a35b427c0bac..388cc128072a 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c | |||
@@ -83,6 +83,8 @@ static struct usb_device *testdev_to_usbdev(struct usbtest_dev *test) | |||
83 | #define WARNING(tdev, fmt, args...) \ | 83 | #define WARNING(tdev, fmt, args...) \ |
84 | dev_warn(&(tdev)->intf->dev , fmt , ## args) | 84 | dev_warn(&(tdev)->intf->dev , fmt , ## args) |
85 | 85 | ||
86 | #define GUARD_BYTE 0xA5 | ||
87 | |||
86 | /*-------------------------------------------------------------------------*/ | 88 | /*-------------------------------------------------------------------------*/ |
87 | 89 | ||
88 | static int | 90 | static int |
@@ -186,11 +188,12 @@ static void simple_callback(struct urb *urb) | |||
186 | complete(urb->context); | 188 | complete(urb->context); |
187 | } | 189 | } |
188 | 190 | ||
189 | static struct urb *simple_alloc_urb( | 191 | static struct urb *usbtest_alloc_urb( |
190 | struct usb_device *udev, | 192 | struct usb_device *udev, |
191 | int pipe, | 193 | int pipe, |
192 | unsigned long bytes | 194 | unsigned long bytes, |
193 | ) | 195 | unsigned transfer_flags, |
196 | unsigned offset) | ||
194 | { | 197 | { |
195 | struct urb *urb; | 198 | struct urb *urb; |
196 | 199 | ||
@@ -201,19 +204,46 @@ static struct urb *simple_alloc_urb( | |||
201 | urb->interval = (udev->speed == USB_SPEED_HIGH) | 204 | urb->interval = (udev->speed == USB_SPEED_HIGH) |
202 | ? (INTERRUPT_RATE << 3) | 205 | ? (INTERRUPT_RATE << 3) |
203 | : INTERRUPT_RATE; | 206 | : INTERRUPT_RATE; |
204 | urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; | 207 | urb->transfer_flags = transfer_flags; |
205 | if (usb_pipein(pipe)) | 208 | if (usb_pipein(pipe)) |
206 | urb->transfer_flags |= URB_SHORT_NOT_OK; | 209 | urb->transfer_flags |= URB_SHORT_NOT_OK; |
207 | urb->transfer_buffer = usb_alloc_coherent(udev, bytes, GFP_KERNEL, | 210 | |
208 | &urb->transfer_dma); | 211 | if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) |
212 | urb->transfer_buffer = usb_alloc_coherent(udev, bytes + offset, | ||
213 | GFP_KERNEL, &urb->transfer_dma); | ||
214 | else | ||
215 | urb->transfer_buffer = kmalloc(bytes + offset, GFP_KERNEL); | ||
216 | |||
209 | if (!urb->transfer_buffer) { | 217 | if (!urb->transfer_buffer) { |
210 | usb_free_urb(urb); | 218 | usb_free_urb(urb); |
211 | urb = NULL; | 219 | return NULL; |
212 | } else | 220 | } |
213 | memset(urb->transfer_buffer, 0, bytes); | 221 | |
222 | /* To test unaligned transfers add an offset and fill the | ||
223 | unused memory with a guard value */ | ||
224 | if (offset) { | ||
225 | memset(urb->transfer_buffer, GUARD_BYTE, offset); | ||
226 | urb->transfer_buffer += offset; | ||
227 | if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) | ||
228 | urb->transfer_dma += offset; | ||
229 | } | ||
230 | |||
231 | /* For inbound transfers use guard byte so that test fails if | ||
232 | data not correctly copied */ | ||
233 | memset(urb->transfer_buffer, | ||
234 | usb_pipein(urb->pipe) ? GUARD_BYTE : 0, | ||
235 | bytes); | ||
214 | return urb; | 236 | return urb; |
215 | } | 237 | } |
216 | 238 | ||
239 | static struct urb *simple_alloc_urb( | ||
240 | struct usb_device *udev, | ||
241 | int pipe, | ||
242 | unsigned long bytes) | ||
243 | { | ||
244 | return usbtest_alloc_urb(udev, pipe, bytes, URB_NO_TRANSFER_DMA_MAP, 0); | ||
245 | } | ||
246 | |||
217 | static unsigned pattern; | 247 | static unsigned pattern; |
218 | static unsigned mod_pattern; | 248 | static unsigned mod_pattern; |
219 | module_param_named(pattern, mod_pattern, uint, S_IRUGO | S_IWUSR); | 249 | module_param_named(pattern, mod_pattern, uint, S_IRUGO | S_IWUSR); |
@@ -238,13 +268,38 @@ static inline void simple_fill_buf(struct urb *urb) | |||
238 | } | 268 | } |
239 | } | 269 | } |
240 | 270 | ||
241 | static inline int simple_check_buf(struct usbtest_dev *tdev, struct urb *urb) | 271 | static inline unsigned buffer_offset(void *buf) |
272 | { | ||
273 | return (unsigned)buf & (ARCH_KMALLOC_MINALIGN - 1); | ||
274 | } | ||
275 | |||
276 | static int check_guard_bytes(struct usbtest_dev *tdev, struct urb *urb) | ||
277 | { | ||
278 | u8 *buf = urb->transfer_buffer; | ||
279 | u8 *guard = buf - buffer_offset(buf); | ||
280 | unsigned i; | ||
281 | |||
282 | for (i = 0; guard < buf; i++, guard++) { | ||
283 | if (*guard != GUARD_BYTE) { | ||
284 | ERROR(tdev, "guard byte[%d] %d (not %d)\n", | ||
285 | i, *guard, GUARD_BYTE); | ||
286 | return -EINVAL; | ||
287 | } | ||
288 | } | ||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | static int simple_check_buf(struct usbtest_dev *tdev, struct urb *urb) | ||
242 | { | 293 | { |
243 | unsigned i; | 294 | unsigned i; |
244 | u8 expected; | 295 | u8 expected; |
245 | u8 *buf = urb->transfer_buffer; | 296 | u8 *buf = urb->transfer_buffer; |
246 | unsigned len = urb->actual_length; | 297 | unsigned len = urb->actual_length; |
247 | 298 | ||
299 | int ret = check_guard_bytes(tdev, urb); | ||
300 | if (ret) | ||
301 | return ret; | ||
302 | |||
248 | for (i = 0; i < len; i++, buf++) { | 303 | for (i = 0; i < len; i++, buf++) { |
249 | switch (pattern) { | 304 | switch (pattern) { |
250 | /* all-zeroes has no synchronization issues */ | 305 | /* all-zeroes has no synchronization issues */ |
@@ -274,8 +329,16 @@ static inline int simple_check_buf(struct usbtest_dev *tdev, struct urb *urb) | |||
274 | 329 | ||
275 | static void simple_free_urb(struct urb *urb) | 330 | static void simple_free_urb(struct urb *urb) |
276 | { | 331 | { |
277 | usb_free_coherent(urb->dev, urb->transfer_buffer_length, | 332 | unsigned offset = buffer_offset(urb->transfer_buffer); |
278 | urb->transfer_buffer, urb->transfer_dma); | 333 | |
334 | if (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP) | ||
335 | usb_free_coherent( | ||
336 | urb->dev, | ||
337 | urb->transfer_buffer_length + offset, | ||
338 | urb->transfer_buffer - offset, | ||
339 | urb->transfer_dma - offset); | ||
340 | else | ||
341 | kfree(urb->transfer_buffer - offset); | ||
279 | usb_free_urb(urb); | 342 | usb_free_urb(urb); |
280 | } | 343 | } |
281 | 344 | ||
@@ -1256,7 +1319,7 @@ done: | |||
1256 | * try whatever we're told to try. | 1319 | * try whatever we're told to try. |
1257 | */ | 1320 | */ |
1258 | static int ctrl_out(struct usbtest_dev *dev, | 1321 | static int ctrl_out(struct usbtest_dev *dev, |
1259 | unsigned count, unsigned length, unsigned vary) | 1322 | unsigned count, unsigned length, unsigned vary, unsigned offset) |
1260 | { | 1323 | { |
1261 | unsigned i, j, len; | 1324 | unsigned i, j, len; |
1262 | int retval; | 1325 | int retval; |
@@ -1267,10 +1330,11 @@ static int ctrl_out(struct usbtest_dev *dev, | |||
1267 | if (length < 1 || length > 0xffff || vary >= length) | 1330 | if (length < 1 || length > 0xffff || vary >= length) |
1268 | return -EINVAL; | 1331 | return -EINVAL; |
1269 | 1332 | ||
1270 | buf = kmalloc(length, GFP_KERNEL); | 1333 | buf = kmalloc(length + offset, GFP_KERNEL); |
1271 | if (!buf) | 1334 | if (!buf) |
1272 | return -ENOMEM; | 1335 | return -ENOMEM; |
1273 | 1336 | ||
1337 | buf += offset; | ||
1274 | udev = testdev_to_usbdev(dev); | 1338 | udev = testdev_to_usbdev(dev); |
1275 | len = length; | 1339 | len = length; |
1276 | retval = 0; | 1340 | retval = 0; |
@@ -1337,7 +1401,7 @@ static int ctrl_out(struct usbtest_dev *dev, | |||
1337 | ERROR(dev, "ctrl_out %s failed, code %d, count %d\n", | 1401 | ERROR(dev, "ctrl_out %s failed, code %d, count %d\n", |
1338 | what, retval, i); | 1402 | what, retval, i); |
1339 | 1403 | ||
1340 | kfree(buf); | 1404 | kfree(buf - offset); |
1341 | return retval; | 1405 | return retval; |
1342 | } | 1406 | } |
1343 | 1407 | ||
@@ -1373,6 +1437,8 @@ static void iso_callback(struct urb *urb) | |||
1373 | ctx->errors += urb->number_of_packets; | 1437 | ctx->errors += urb->number_of_packets; |
1374 | else if (urb->actual_length != urb->transfer_buffer_length) | 1438 | else if (urb->actual_length != urb->transfer_buffer_length) |
1375 | ctx->errors++; | 1439 | ctx->errors++; |
1440 | else if (check_guard_bytes(ctx->dev, urb) != 0) | ||
1441 | ctx->errors++; | ||
1376 | 1442 | ||
1377 | if (urb->status == 0 && ctx->count > (ctx->pending - 1) | 1443 | if (urb->status == 0 && ctx->count > (ctx->pending - 1) |
1378 | && !ctx->submit_error) { | 1444 | && !ctx->submit_error) { |
@@ -1408,7 +1474,8 @@ static struct urb *iso_alloc_urb( | |||
1408 | struct usb_device *udev, | 1474 | struct usb_device *udev, |
1409 | int pipe, | 1475 | int pipe, |
1410 | struct usb_endpoint_descriptor *desc, | 1476 | struct usb_endpoint_descriptor *desc, |
1411 | long bytes | 1477 | long bytes, |
1478 | unsigned offset | ||
1412 | ) | 1479 | ) |
1413 | { | 1480 | { |
1414 | struct urb *urb; | 1481 | struct urb *urb; |
@@ -1428,13 +1495,24 @@ static struct urb *iso_alloc_urb( | |||
1428 | 1495 | ||
1429 | urb->number_of_packets = packets; | 1496 | urb->number_of_packets = packets; |
1430 | urb->transfer_buffer_length = bytes; | 1497 | urb->transfer_buffer_length = bytes; |
1431 | urb->transfer_buffer = usb_alloc_coherent(udev, bytes, GFP_KERNEL, | 1498 | urb->transfer_buffer = usb_alloc_coherent(udev, bytes + offset, |
1432 | &urb->transfer_dma); | 1499 | GFP_KERNEL, |
1500 | &urb->transfer_dma); | ||
1433 | if (!urb->transfer_buffer) { | 1501 | if (!urb->transfer_buffer) { |
1434 | usb_free_urb(urb); | 1502 | usb_free_urb(urb); |
1435 | return NULL; | 1503 | return NULL; |
1436 | } | 1504 | } |
1437 | memset(urb->transfer_buffer, 0, bytes); | 1505 | if (offset) { |
1506 | memset(urb->transfer_buffer, GUARD_BYTE, offset); | ||
1507 | urb->transfer_buffer += offset; | ||
1508 | urb->transfer_dma += offset; | ||
1509 | } | ||
1510 | /* For inbound transfers use guard byte so that test fails if | ||
1511 | data not correctly copied */ | ||
1512 | memset(urb->transfer_buffer, | ||
1513 | usb_pipein(urb->pipe) ? GUARD_BYTE : 0, | ||
1514 | bytes); | ||
1515 | |||
1438 | for (i = 0; i < packets; i++) { | 1516 | for (i = 0; i < packets; i++) { |
1439 | /* here, only the last packet will be short */ | 1517 | /* here, only the last packet will be short */ |
1440 | urb->iso_frame_desc[i].length = min((unsigned) bytes, maxp); | 1518 | urb->iso_frame_desc[i].length = min((unsigned) bytes, maxp); |
@@ -1452,7 +1530,7 @@ static struct urb *iso_alloc_urb( | |||
1452 | 1530 | ||
1453 | static int | 1531 | static int |
1454 | test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param, | 1532 | test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param, |
1455 | int pipe, struct usb_endpoint_descriptor *desc) | 1533 | int pipe, struct usb_endpoint_descriptor *desc, unsigned offset) |
1456 | { | 1534 | { |
1457 | struct iso_context context; | 1535 | struct iso_context context; |
1458 | struct usb_device *udev; | 1536 | struct usb_device *udev; |
@@ -1480,7 +1558,7 @@ test_iso_queue(struct usbtest_dev *dev, struct usbtest_param *param, | |||
1480 | 1558 | ||
1481 | for (i = 0; i < param->sglen; i++) { | 1559 | for (i = 0; i < param->sglen; i++) { |
1482 | urbs[i] = iso_alloc_urb(udev, pipe, desc, | 1560 | urbs[i] = iso_alloc_urb(udev, pipe, desc, |
1483 | param->length); | 1561 | param->length, offset); |
1484 | if (!urbs[i]) { | 1562 | if (!urbs[i]) { |
1485 | status = -ENOMEM; | 1563 | status = -ENOMEM; |
1486 | goto fail; | 1564 | goto fail; |
@@ -1542,6 +1620,26 @@ fail: | |||
1542 | return status; | 1620 | return status; |
1543 | } | 1621 | } |
1544 | 1622 | ||
1623 | static int test_unaligned_bulk( | ||
1624 | struct usbtest_dev *tdev, | ||
1625 | int pipe, | ||
1626 | unsigned length, | ||
1627 | int iterations, | ||
1628 | unsigned transfer_flags, | ||
1629 | const char *label) | ||
1630 | { | ||
1631 | int retval; | ||
1632 | struct urb *urb = usbtest_alloc_urb( | ||
1633 | testdev_to_usbdev(tdev), pipe, length, transfer_flags, 1); | ||
1634 | |||
1635 | if (!urb) | ||
1636 | return -ENOMEM; | ||
1637 | |||
1638 | retval = simple_io(tdev, urb, iterations, 0, 0, label); | ||
1639 | simple_free_urb(urb); | ||
1640 | return retval; | ||
1641 | } | ||
1642 | |||
1545 | /*-------------------------------------------------------------------------*/ | 1643 | /*-------------------------------------------------------------------------*/ |
1546 | 1644 | ||
1547 | /* We only have this one interface to user space, through usbfs. | 1645 | /* We only have this one interface to user space, through usbfs. |
@@ -1843,7 +1941,7 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf) | |||
1843 | realworld ? 1 : 0, param->length, | 1941 | realworld ? 1 : 0, param->length, |
1844 | param->vary); | 1942 | param->vary); |
1845 | retval = ctrl_out(dev, param->iterations, | 1943 | retval = ctrl_out(dev, param->iterations, |
1846 | param->length, param->vary); | 1944 | param->length, param->vary, 0); |
1847 | break; | 1945 | break; |
1848 | 1946 | ||
1849 | /* iso write tests */ | 1947 | /* iso write tests */ |
@@ -1856,7 +1954,7 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf) | |||
1856 | param->sglen, param->length); | 1954 | param->sglen, param->length); |
1857 | /* FIRMWARE: iso sink */ | 1955 | /* FIRMWARE: iso sink */ |
1858 | retval = test_iso_queue(dev, param, | 1956 | retval = test_iso_queue(dev, param, |
1859 | dev->out_iso_pipe, dev->iso_out); | 1957 | dev->out_iso_pipe, dev->iso_out, 0); |
1860 | break; | 1958 | break; |
1861 | 1959 | ||
1862 | /* iso read tests */ | 1960 | /* iso read tests */ |
@@ -1869,13 +1967,103 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf) | |||
1869 | param->sglen, param->length); | 1967 | param->sglen, param->length); |
1870 | /* FIRMWARE: iso source */ | 1968 | /* FIRMWARE: iso source */ |
1871 | retval = test_iso_queue(dev, param, | 1969 | retval = test_iso_queue(dev, param, |
1872 | dev->in_iso_pipe, dev->iso_in); | 1970 | dev->in_iso_pipe, dev->iso_in, 0); |
1873 | break; | 1971 | break; |
1874 | 1972 | ||
1875 | /* FIXME unlink from queue (ring with N urbs) */ | 1973 | /* FIXME unlink from queue (ring with N urbs) */ |
1876 | 1974 | ||
1877 | /* FIXME scatterlist cancel (needs helper thread) */ | 1975 | /* FIXME scatterlist cancel (needs helper thread) */ |
1878 | 1976 | ||
1977 | /* Tests for bulk I/O using DMA mapping by core and odd address */ | ||
1978 | case 17: | ||
1979 | if (dev->out_pipe == 0) | ||
1980 | break; | ||
1981 | dev_info(&intf->dev, | ||
1982 | "TEST 17: write odd addr %d bytes %u times core map\n", | ||
1983 | param->length, param->iterations); | ||
1984 | |||
1985 | retval = test_unaligned_bulk( | ||
1986 | dev, dev->out_pipe, | ||
1987 | param->length, param->iterations, | ||
1988 | 0, "test17"); | ||
1989 | break; | ||
1990 | |||
1991 | case 18: | ||
1992 | if (dev->in_pipe == 0) | ||
1993 | break; | ||
1994 | dev_info(&intf->dev, | ||
1995 | "TEST 18: read odd addr %d bytes %u times core map\n", | ||
1996 | param->length, param->iterations); | ||
1997 | |||
1998 | retval = test_unaligned_bulk( | ||
1999 | dev, dev->in_pipe, | ||
2000 | param->length, param->iterations, | ||
2001 | 0, "test18"); | ||
2002 | break; | ||
2003 | |||
2004 | /* Tests for bulk I/O using premapped coherent buffer and odd address */ | ||
2005 | case 19: | ||
2006 | if (dev->out_pipe == 0) | ||
2007 | break; | ||
2008 | dev_info(&intf->dev, | ||
2009 | "TEST 19: write odd addr %d bytes %u times premapped\n", | ||
2010 | param->length, param->iterations); | ||
2011 | |||
2012 | retval = test_unaligned_bulk( | ||
2013 | dev, dev->out_pipe, | ||
2014 | param->length, param->iterations, | ||
2015 | URB_NO_TRANSFER_DMA_MAP, "test19"); | ||
2016 | break; | ||
2017 | |||
2018 | case 20: | ||
2019 | if (dev->in_pipe == 0) | ||
2020 | break; | ||
2021 | dev_info(&intf->dev, | ||
2022 | "TEST 20: read odd addr %d bytes %u times premapped\n", | ||
2023 | param->length, param->iterations); | ||
2024 | |||
2025 | retval = test_unaligned_bulk( | ||
2026 | dev, dev->in_pipe, | ||
2027 | param->length, param->iterations, | ||
2028 | URB_NO_TRANSFER_DMA_MAP, "test20"); | ||
2029 | break; | ||
2030 | |||
2031 | /* control write tests with unaligned buffer */ | ||
2032 | case 21: | ||
2033 | if (!dev->info->ctrl_out) | ||
2034 | break; | ||
2035 | dev_info(&intf->dev, | ||
2036 | "TEST 21: %d ep0out odd addr, %d..%d vary %d\n", | ||
2037 | param->iterations, | ||
2038 | realworld ? 1 : 0, param->length, | ||
2039 | param->vary); | ||
2040 | retval = ctrl_out(dev, param->iterations, | ||
2041 | param->length, param->vary, 1); | ||
2042 | break; | ||
2043 | |||
2044 | /* unaligned iso tests */ | ||
2045 | case 22: | ||
2046 | if (dev->out_iso_pipe == 0 || param->sglen == 0) | ||
2047 | break; | ||
2048 | dev_info(&intf->dev, | ||
2049 | "TEST 22: write %d iso odd, %d entries of %d bytes\n", | ||
2050 | param->iterations, | ||
2051 | param->sglen, param->length); | ||
2052 | retval = test_iso_queue(dev, param, | ||
2053 | dev->out_iso_pipe, dev->iso_out, 1); | ||
2054 | break; | ||
2055 | |||
2056 | case 23: | ||
2057 | if (dev->in_iso_pipe == 0 || param->sglen == 0) | ||
2058 | break; | ||
2059 | dev_info(&intf->dev, | ||
2060 | "TEST 23: read %d iso odd, %d entries of %d bytes\n", | ||
2061 | param->iterations, | ||
2062 | param->sglen, param->length); | ||
2063 | retval = test_iso_queue(dev, param, | ||
2064 | dev->in_iso_pipe, dev->iso_in, 1); | ||
2065 | break; | ||
2066 | |||
1879 | } | 2067 | } |
1880 | do_gettimeofday(¶m->duration); | 2068 | do_gettimeofday(¶m->duration); |
1881 | param->duration.tv_sec -= start.tv_sec; | 2069 | param->duration.tv_sec -= start.tv_sec; |