aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/misc/usbtest.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/misc/usbtest.c')
-rw-r--r--drivers/usb/misc/usbtest.c38
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 }
1376done: 1386done:
@@ -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
1491fail: 1515fail:
1492 for (i = 0; i < param->sglen; i++) { 1516 for (i = 0; i < param->sglen; i++) {