diff options
Diffstat (limited to 'drivers/usb/misc/usbtest.c')
-rw-r--r-- | drivers/usb/misc/usbtest.c | 38 |
1 files changed, 31 insertions, 7 deletions
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index ccc5e8238bd8..81ba14c73dc7 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c | |||
@@ -802,7 +802,9 @@ error: | |||
802 | 802 | ||
803 | if (u == urb || !u->dev) | 803 | if (u == urb || !u->dev) |
804 | continue; | 804 | continue; |
805 | spin_unlock(&ctx->lock); | ||
805 | status = usb_unlink_urb (u); | 806 | status = usb_unlink_urb (u); |
807 | spin_lock(&ctx->lock); | ||
806 | switch (status) { | 808 | switch (status) { |
807 | case -EINPROGRESS: | 809 | case -EINPROGRESS: |
808 | case -EBUSY: | 810 | case -EBUSY: |
@@ -1335,7 +1337,9 @@ struct iso_context { | |||
1335 | unsigned pending; | 1337 | unsigned pending; |
1336 | spinlock_t lock; | 1338 | spinlock_t lock; |
1337 | struct completion done; | 1339 | struct completion done; |
1340 | int submit_error; | ||
1338 | unsigned long errors; | 1341 | unsigned long errors; |
1342 | unsigned long packet_count; | ||
1339 | struct usbtest_dev *dev; | 1343 | struct usbtest_dev *dev; |
1340 | }; | 1344 | }; |
1341 | 1345 | ||
@@ -1346,10 +1350,14 @@ static void iso_callback (struct urb *urb, struct pt_regs *regs) | |||
1346 | spin_lock(&ctx->lock); | 1350 | spin_lock(&ctx->lock); |
1347 | ctx->count--; | 1351 | ctx->count--; |
1348 | 1352 | ||
1353 | ctx->packet_count += urb->number_of_packets; | ||
1349 | if (urb->error_count > 0) | 1354 | if (urb->error_count > 0) |
1350 | ctx->errors += urb->error_count; | 1355 | ctx->errors += urb->error_count; |
1356 | else if (urb->status != 0) | ||
1357 | ctx->errors += urb->number_of_packets; | ||
1351 | 1358 | ||
1352 | if (urb->status == 0 && ctx->count > (ctx->pending - 1)) { | 1359 | if (urb->status == 0 && ctx->count > (ctx->pending - 1) |
1360 | && !ctx->submit_error) { | ||
1353 | int status = usb_submit_urb (urb, GFP_ATOMIC); | 1361 | int status = usb_submit_urb (urb, GFP_ATOMIC); |
1354 | switch (status) { | 1362 | switch (status) { |
1355 | case 0: | 1363 | case 0: |
@@ -1360,6 +1368,8 @@ static void iso_callback (struct urb *urb, struct pt_regs *regs) | |||
1360 | status); | 1368 | status); |
1361 | /* FALLTHROUGH */ | 1369 | /* FALLTHROUGH */ |
1362 | case -ENODEV: /* disconnected */ | 1370 | case -ENODEV: /* disconnected */ |
1371 | case -ESHUTDOWN: /* endpoint disabled */ | ||
1372 | ctx->submit_error = 1; | ||
1363 | break; | 1373 | break; |
1364 | } | 1374 | } |
1365 | } | 1375 | } |
@@ -1369,8 +1379,8 @@ static void iso_callback (struct urb *urb, struct pt_regs *regs) | |||
1369 | if (ctx->pending == 0) { | 1379 | if (ctx->pending == 0) { |
1370 | if (ctx->errors) | 1380 | if (ctx->errors) |
1371 | dev_dbg (&ctx->dev->intf->dev, | 1381 | dev_dbg (&ctx->dev->intf->dev, |
1372 | "iso test, %lu errors\n", | 1382 | "iso test, %lu errors out of %lu\n", |
1373 | ctx->errors); | 1383 | ctx->errors, ctx->packet_count); |
1374 | complete (&ctx->done); | 1384 | complete (&ctx->done); |
1375 | } | 1385 | } |
1376 | done: | 1386 | done: |
@@ -1431,15 +1441,14 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param, | |||
1431 | struct usb_device *udev; | 1441 | struct usb_device *udev; |
1432 | unsigned i; | 1442 | unsigned i; |
1433 | unsigned long packets = 0; | 1443 | unsigned long packets = 0; |
1434 | int status; | 1444 | int status = 0; |
1435 | struct urb *urbs[10]; /* FIXME no limit */ | 1445 | struct urb *urbs[10]; /* FIXME no limit */ |
1436 | 1446 | ||
1437 | if (param->sglen > 10) | 1447 | if (param->sglen > 10) |
1438 | return -EDOM; | 1448 | return -EDOM; |
1439 | 1449 | ||
1450 | memset(&context, 0, sizeof context); | ||
1440 | context.count = param->iterations * param->sglen; | 1451 | context.count = param->iterations * param->sglen; |
1441 | context.pending = param->sglen; | ||
1442 | context.errors = 0; | ||
1443 | context.dev = dev; | 1452 | context.dev = dev; |
1444 | init_completion (&context.done); | 1453 | init_completion (&context.done); |
1445 | spin_lock_init (&context.lock); | 1454 | spin_lock_init (&context.lock); |
@@ -1471,6 +1480,7 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param, | |||
1471 | 1480 | ||
1472 | spin_lock_irq (&context.lock); | 1481 | spin_lock_irq (&context.lock); |
1473 | for (i = 0; i < param->sglen; i++) { | 1482 | for (i = 0; i < param->sglen; i++) { |
1483 | ++context.pending; | ||
1474 | status = usb_submit_urb (urbs [i], SLAB_ATOMIC); | 1484 | status = usb_submit_urb (urbs [i], SLAB_ATOMIC); |
1475 | if (status < 0) { | 1485 | if (status < 0) { |
1476 | ERROR (dev, "submit iso[%d], error %d\n", i, status); | 1486 | ERROR (dev, "submit iso[%d], error %d\n", i, status); |
@@ -1481,12 +1491,26 @@ test_iso_queue (struct usbtest_dev *dev, struct usbtest_param *param, | |||
1481 | 1491 | ||
1482 | simple_free_urb (urbs [i]); | 1492 | simple_free_urb (urbs [i]); |
1483 | context.pending--; | 1493 | context.pending--; |
1494 | context.submit_error = 1; | ||
1495 | break; | ||
1484 | } | 1496 | } |
1485 | } | 1497 | } |
1486 | spin_unlock_irq (&context.lock); | 1498 | spin_unlock_irq (&context.lock); |
1487 | 1499 | ||
1488 | wait_for_completion (&context.done); | 1500 | wait_for_completion (&context.done); |
1489 | return 0; | 1501 | |
1502 | /* | ||
1503 | * Isochronous transfers are expected to fail sometimes. As an | ||
1504 | * arbitrary limit, we will report an error if any submissions | ||
1505 | * fail or if the transfer failure rate is > 10%. | ||
1506 | */ | ||
1507 | if (status != 0) | ||
1508 | ; | ||
1509 | else if (context.submit_error) | ||
1510 | status = -EACCES; | ||
1511 | else if (context.errors > context.packet_count / 10) | ||
1512 | status = -EIO; | ||
1513 | return status; | ||
1490 | 1514 | ||
1491 | fail: | 1515 | fail: |
1492 | for (i = 0; i < param->sglen; i++) { | 1516 | for (i = 0; i < param->sglen; i++) { |