diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/core/devio.c | 6 | ||||
-rw-r--r-- | drivers/usb/core/hcd.c | 14 | ||||
-rw-r--r-- | drivers/usb/core/hub.c | 11 | ||||
-rw-r--r-- | drivers/usb/core/usb.h | 1 | ||||
-rw-r--r-- | drivers/usb/host/ehci-fsl.c | 2 | ||||
-rw-r--r-- | drivers/usb/host/ehci-sched.c | 180 | ||||
-rw-r--r-- | drivers/usb/host/ehci.h | 1 |
7 files changed, 134 insertions, 81 deletions
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 737e3c19967b..f4f2300f8e10 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c | |||
@@ -898,10 +898,8 @@ static int proc_control(struct dev_state *ps, void __user *arg) | |||
898 | snoop(&dev->dev, "control urb: bRequestType=%02x " | 898 | snoop(&dev->dev, "control urb: bRequestType=%02x " |
899 | "bRequest=%02x wValue=%04x " | 899 | "bRequest=%02x wValue=%04x " |
900 | "wIndex=%04x wLength=%04x\n", | 900 | "wIndex=%04x wLength=%04x\n", |
901 | ctrl.bRequestType, ctrl.bRequest, | 901 | ctrl.bRequestType, ctrl.bRequest, ctrl.wValue, |
902 | __le16_to_cpup(&ctrl.wValue), | 902 | ctrl.wIndex, ctrl.wLength); |
903 | __le16_to_cpup(&ctrl.wIndex), | ||
904 | __le16_to_cpup(&ctrl.wLength)); | ||
905 | if (ctrl.bRequestType & 0x80) { | 903 | if (ctrl.bRequestType & 0x80) { |
906 | if (ctrl.wLength && !access_ok(VERIFY_WRITE, ctrl.data, | 904 | if (ctrl.wLength && !access_ok(VERIFY_WRITE, ctrl.data, |
907 | ctrl.wLength)) { | 905 | ctrl.wLength)) { |
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index d6a8d23f047b..9795a21bc612 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -1033,6 +1033,7 @@ static int register_root_hub(struct usb_hcd *hcd) | |||
1033 | dev_name(&usb_dev->dev), retval); | 1033 | dev_name(&usb_dev->dev), retval); |
1034 | return retval; | 1034 | return retval; |
1035 | } | 1035 | } |
1036 | usb_dev->lpm_capable = usb_device_supports_lpm(usb_dev); | ||
1036 | } | 1037 | } |
1037 | 1038 | ||
1038 | retval = usb_new_device (usb_dev); | 1039 | retval = usb_new_device (usb_dev); |
@@ -1703,7 +1704,9 @@ static void usb_giveback_urb_bh(unsigned long param) | |||
1703 | 1704 | ||
1704 | urb = list_entry(local_list.next, struct urb, urb_list); | 1705 | urb = list_entry(local_list.next, struct urb, urb_list); |
1705 | list_del_init(&urb->urb_list); | 1706 | list_del_init(&urb->urb_list); |
1707 | bh->completing_ep = urb->ep; | ||
1706 | __usb_hcd_giveback_urb(urb); | 1708 | __usb_hcd_giveback_urb(urb); |
1709 | bh->completing_ep = NULL; | ||
1707 | } | 1710 | } |
1708 | 1711 | ||
1709 | /* check if there are new URBs to giveback */ | 1712 | /* check if there are new URBs to giveback */ |
@@ -2073,8 +2076,11 @@ EXPORT_SYMBOL_GPL(usb_alloc_streams); | |||
2073 | * | 2076 | * |
2074 | * Reverts a group of bulk endpoints back to not using stream IDs. | 2077 | * Reverts a group of bulk endpoints back to not using stream IDs. |
2075 | * Can fail if we are given bad arguments, or HCD is broken. | 2078 | * Can fail if we are given bad arguments, or HCD is broken. |
2079 | * | ||
2080 | * Return: On success, the number of allocated streams. On failure, a negative | ||
2081 | * error code. | ||
2076 | */ | 2082 | */ |
2077 | void usb_free_streams(struct usb_interface *interface, | 2083 | int usb_free_streams(struct usb_interface *interface, |
2078 | struct usb_host_endpoint **eps, unsigned int num_eps, | 2084 | struct usb_host_endpoint **eps, unsigned int num_eps, |
2079 | gfp_t mem_flags) | 2085 | gfp_t mem_flags) |
2080 | { | 2086 | { |
@@ -2085,14 +2091,14 @@ void usb_free_streams(struct usb_interface *interface, | |||
2085 | dev = interface_to_usbdev(interface); | 2091 | dev = interface_to_usbdev(interface); |
2086 | hcd = bus_to_hcd(dev->bus); | 2092 | hcd = bus_to_hcd(dev->bus); |
2087 | if (dev->speed != USB_SPEED_SUPER) | 2093 | if (dev->speed != USB_SPEED_SUPER) |
2088 | return; | 2094 | return -EINVAL; |
2089 | 2095 | ||
2090 | /* Streams only apply to bulk endpoints. */ | 2096 | /* Streams only apply to bulk endpoints. */ |
2091 | for (i = 0; i < num_eps; i++) | 2097 | for (i = 0; i < num_eps; i++) |
2092 | if (!eps[i] || !usb_endpoint_xfer_bulk(&eps[i]->desc)) | 2098 | if (!eps[i] || !usb_endpoint_xfer_bulk(&eps[i]->desc)) |
2093 | return; | 2099 | return -EINVAL; |
2094 | 2100 | ||
2095 | hcd->driver->free_streams(hcd, dev, eps, num_eps, mem_flags); | 2101 | return hcd->driver->free_streams(hcd, dev, eps, num_eps, mem_flags); |
2096 | } | 2102 | } |
2097 | EXPORT_SYMBOL_GPL(usb_free_streams); | 2103 | EXPORT_SYMBOL_GPL(usb_free_streams); |
2098 | 2104 | ||
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index dde4c83516a1..6f783bfe2959 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -135,7 +135,7 @@ struct usb_hub *usb_hub_to_struct_hub(struct usb_device *hdev) | |||
135 | return usb_get_intfdata(hdev->actconfig->interface[0]); | 135 | return usb_get_intfdata(hdev->actconfig->interface[0]); |
136 | } | 136 | } |
137 | 137 | ||
138 | static int usb_device_supports_lpm(struct usb_device *udev) | 138 | int usb_device_supports_lpm(struct usb_device *udev) |
139 | { | 139 | { |
140 | /* USB 2.1 (and greater) devices indicate LPM support through | 140 | /* USB 2.1 (and greater) devices indicate LPM support through |
141 | * their USB 2.0 Extended Capabilities BOS descriptor. | 141 | * their USB 2.0 Extended Capabilities BOS descriptor. |
@@ -156,6 +156,11 @@ static int usb_device_supports_lpm(struct usb_device *udev) | |||
156 | "Power management will be impacted.\n"); | 156 | "Power management will be impacted.\n"); |
157 | return 0; | 157 | return 0; |
158 | } | 158 | } |
159 | |||
160 | /* udev is root hub */ | ||
161 | if (!udev->parent) | ||
162 | return 1; | ||
163 | |||
159 | if (udev->parent->lpm_capable) | 164 | if (udev->parent->lpm_capable) |
160 | return 1; | 165 | return 1; |
161 | 166 | ||
@@ -310,9 +315,9 @@ static void usb_set_lpm_parameters(struct usb_device *udev) | |||
310 | return; | 315 | return; |
311 | 316 | ||
312 | udev_u1_del = udev->bos->ss_cap->bU1devExitLat; | 317 | udev_u1_del = udev->bos->ss_cap->bU1devExitLat; |
313 | udev_u2_del = udev->bos->ss_cap->bU2DevExitLat; | 318 | udev_u2_del = le16_to_cpu(udev->bos->ss_cap->bU2DevExitLat); |
314 | hub_u1_del = udev->parent->bos->ss_cap->bU1devExitLat; | 319 | hub_u1_del = udev->parent->bos->ss_cap->bU1devExitLat; |
315 | hub_u2_del = udev->parent->bos->ss_cap->bU2DevExitLat; | 320 | hub_u2_del = le16_to_cpu(udev->parent->bos->ss_cap->bU2DevExitLat); |
316 | 321 | ||
317 | usb_set_lpm_mel(udev, &udev->u1_params, udev_u1_del, | 322 | usb_set_lpm_mel(udev, &udev->u1_params, udev_u1_del, |
318 | hub, &udev->parent->u1_params, hub_u1_del); | 323 | hub, &udev->parent->u1_params, hub_u1_del); |
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 823857767a16..c49383669cd8 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h | |||
@@ -35,6 +35,7 @@ extern int usb_get_device_descriptor(struct usb_device *dev, | |||
35 | unsigned int size); | 35 | unsigned int size); |
36 | extern int usb_get_bos_descriptor(struct usb_device *dev); | 36 | extern int usb_get_bos_descriptor(struct usb_device *dev); |
37 | extern void usb_release_bos_descriptor(struct usb_device *dev); | 37 | extern void usb_release_bos_descriptor(struct usb_device *dev); |
38 | extern int usb_device_supports_lpm(struct usb_device *udev); | ||
38 | extern char *usb_cache_string(struct usb_device *udev, int index); | 39 | extern char *usb_cache_string(struct usb_device *udev, int index); |
39 | extern int usb_set_configuration(struct usb_device *dev, int configuration); | 40 | extern int usb_set_configuration(struct usb_device *dev, int configuration); |
40 | extern int usb_choose_configuration(struct usb_device *udev); | 41 | extern int usb_choose_configuration(struct usb_device *udev); |
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 4449f565d6c6..848fc46ad80c 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c | |||
@@ -57,7 +57,7 @@ static int usb_hcd_fsl_probe(const struct hc_driver *driver, | |||
57 | pr_debug("initializing FSL-SOC USB Controller\n"); | 57 | pr_debug("initializing FSL-SOC USB Controller\n"); |
58 | 58 | ||
59 | /* Need platform data for setup */ | 59 | /* Need platform data for setup */ |
60 | pdata = (struct fsl_usb2_platform_data *)dev_get_platdata(&pdev->dev); | 60 | pdata = dev_get_platdata(&pdev->dev); |
61 | if (!pdata) { | 61 | if (!pdata) { |
62 | dev_err(&pdev->dev, | 62 | dev_err(&pdev->dev, |
63 | "No platform data for %s.\n", dev_name(&pdev->dev)); | 63 | "No platform data for %s.\n", dev_name(&pdev->dev)); |
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 85dd24ed97a6..dcbaad94d607 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
@@ -1370,10 +1370,12 @@ iso_stream_schedule ( | |||
1370 | struct ehci_iso_stream *stream | 1370 | struct ehci_iso_stream *stream |
1371 | ) | 1371 | ) |
1372 | { | 1372 | { |
1373 | u32 now, base, next, start, period, span; | 1373 | u32 now, base, next, start, period, span, now2; |
1374 | int status; | 1374 | u32 wrap = 0, skip = 0; |
1375 | int status = 0; | ||
1375 | unsigned mod = ehci->periodic_size << 3; | 1376 | unsigned mod = ehci->periodic_size << 3; |
1376 | struct ehci_iso_sched *sched = urb->hcpriv; | 1377 | struct ehci_iso_sched *sched = urb->hcpriv; |
1378 | bool empty = list_empty(&stream->td_list); | ||
1377 | 1379 | ||
1378 | period = urb->interval; | 1380 | period = urb->interval; |
1379 | span = sched->span; | 1381 | span = sched->span; |
@@ -1384,69 +1386,31 @@ iso_stream_schedule ( | |||
1384 | 1386 | ||
1385 | now = ehci_read_frame_index(ehci) & (mod - 1); | 1387 | now = ehci_read_frame_index(ehci) & (mod - 1); |
1386 | 1388 | ||
1387 | /* Typical case: reuse current schedule, stream is still active. | 1389 | /* Take the isochronous scheduling threshold into account */ |
1388 | * Hopefully there are no gaps from the host falling behind | 1390 | if (ehci->i_thresh) |
1389 | * (irq delays etc). If there are, the behavior depends on | 1391 | next = now + ehci->i_thresh; /* uframe cache */ |
1390 | * whether URB_ISO_ASAP is set. | 1392 | else |
1391 | */ | 1393 | next = (now + 2 + 7) & ~0x07; /* full frame cache */ |
1392 | if (likely (!list_empty (&stream->td_list))) { | ||
1393 | |||
1394 | /* Take the isochronous scheduling threshold into account */ | ||
1395 | if (ehci->i_thresh) | ||
1396 | next = now + ehci->i_thresh; /* uframe cache */ | ||
1397 | else | ||
1398 | next = (now + 2 + 7) & ~0x07; /* full frame cache */ | ||
1399 | |||
1400 | /* | ||
1401 | * Use ehci->last_iso_frame as the base. There can't be any | ||
1402 | * TDs scheduled for earlier than that. | ||
1403 | */ | ||
1404 | base = ehci->last_iso_frame << 3; | ||
1405 | next = (next - base) & (mod - 1); | ||
1406 | start = (stream->next_uframe - base) & (mod - 1); | ||
1407 | |||
1408 | /* Is the schedule already full? */ | ||
1409 | if (unlikely(start < period)) { | ||
1410 | ehci_dbg(ehci, "iso sched full %p (%u-%u < %u mod %u)\n", | ||
1411 | urb, stream->next_uframe, base, | ||
1412 | period, mod); | ||
1413 | status = -ENOSPC; | ||
1414 | goto fail; | ||
1415 | } | ||
1416 | |||
1417 | /* Behind the scheduling threshold? */ | ||
1418 | if (unlikely(start < next)) { | ||
1419 | unsigned now2 = (now - base) & (mod - 1); | ||
1420 | |||
1421 | /* USB_ISO_ASAP: Round up to the first available slot */ | ||
1422 | if (urb->transfer_flags & URB_ISO_ASAP) | ||
1423 | start += (next - start + period - 1) & -period; | ||
1424 | |||
1425 | /* | ||
1426 | * Not ASAP: Use the next slot in the stream, | ||
1427 | * no matter what. | ||
1428 | */ | ||
1429 | else if (start + span - period < now2) { | ||
1430 | ehci_dbg(ehci, "iso underrun %p (%u+%u < %u)\n", | ||
1431 | urb, start + base, | ||
1432 | span - period, now2 + base); | ||
1433 | } | ||
1434 | } | ||
1435 | 1394 | ||
1436 | start += base; | 1395 | /* |
1437 | } | 1396 | * Use ehci->last_iso_frame as the base. There can't be any |
1397 | * TDs scheduled for earlier than that. | ||
1398 | */ | ||
1399 | base = ehci->last_iso_frame << 3; | ||
1400 | next = (next - base) & (mod - 1); | ||
1438 | 1401 | ||
1439 | /* need to schedule; when's the next (u)frame we could start? | 1402 | /* |
1440 | * this is bigger than ehci->i_thresh allows; scheduling itself | 1403 | * Need to schedule; when's the next (u)frame we could start? |
1441 | * isn't free, the delay should handle reasonably slow cpus. it | 1404 | * This is bigger than ehci->i_thresh allows; scheduling itself |
1405 | * isn't free, the delay should handle reasonably slow cpus. It | ||
1442 | * can also help high bandwidth if the dma and irq loads don't | 1406 | * can also help high bandwidth if the dma and irq loads don't |
1443 | * jump until after the queue is primed. | 1407 | * jump until after the queue is primed. |
1444 | */ | 1408 | */ |
1445 | else { | 1409 | if (unlikely(empty && !hcd_periodic_completion_in_progress( |
1410 | ehci_to_hcd(ehci), urb->ep))) { | ||
1446 | int done = 0; | 1411 | int done = 0; |
1447 | 1412 | ||
1448 | base = now & ~0x07; | 1413 | start = (now & ~0x07) + SCHEDULING_DELAY; |
1449 | start = base + SCHEDULING_DELAY; | ||
1450 | 1414 | ||
1451 | /* find a uframe slot with enough bandwidth. | 1415 | /* find a uframe slot with enough bandwidth. |
1452 | * Early uframes are more precious because full-speed | 1416 | * Early uframes are more precious because full-speed |
@@ -1477,27 +1441,96 @@ iso_stream_schedule ( | |||
1477 | status = -ENOSPC; | 1441 | status = -ENOSPC; |
1478 | goto fail; | 1442 | goto fail; |
1479 | } | 1443 | } |
1444 | |||
1445 | start = (start - base) & (mod - 1); | ||
1446 | goto use_start; | ||
1480 | } | 1447 | } |
1481 | 1448 | ||
1449 | /* | ||
1450 | * Typical case: reuse current schedule, stream is still active. | ||
1451 | * Hopefully there are no gaps from the host falling behind | ||
1452 | * (irq delays etc). If there are, the behavior depends on | ||
1453 | * whether URB_ISO_ASAP is set. | ||
1454 | */ | ||
1455 | start = (stream->next_uframe - base) & (mod - 1); | ||
1456 | now2 = (now - base) & (mod - 1); | ||
1457 | |||
1458 | /* Is the schedule already full? */ | ||
1459 | if (unlikely(!empty && start < period)) { | ||
1460 | ehci_dbg(ehci, "iso sched full %p (%u-%u < %u mod %u)\n", | ||
1461 | urb, stream->next_uframe, base, period, mod); | ||
1462 | status = -ENOSPC; | ||
1463 | goto fail; | ||
1464 | } | ||
1465 | |||
1466 | /* Is the next packet scheduled after the base time? */ | ||
1467 | if (likely(!empty || start <= now2 + period)) { | ||
1468 | |||
1469 | /* URB_ISO_ASAP: make sure that start >= next */ | ||
1470 | if (unlikely(start < next && | ||
1471 | (urb->transfer_flags & URB_ISO_ASAP))) | ||
1472 | goto do_ASAP; | ||
1473 | |||
1474 | /* Otherwise use start, if it's not in the past */ | ||
1475 | if (likely(start >= now2)) | ||
1476 | goto use_start; | ||
1477 | |||
1478 | /* Otherwise we got an underrun while the queue was empty */ | ||
1479 | } else { | ||
1480 | if (urb->transfer_flags & URB_ISO_ASAP) | ||
1481 | goto do_ASAP; | ||
1482 | wrap = mod; | ||
1483 | now2 += mod; | ||
1484 | } | ||
1485 | |||
1486 | /* How many uframes and packets do we need to skip? */ | ||
1487 | skip = (now2 - start + period - 1) & -period; | ||
1488 | if (skip >= span) { /* Entirely in the past? */ | ||
1489 | ehci_dbg(ehci, "iso underrun %p (%u+%u < %u) [%u]\n", | ||
1490 | urb, start + base, span - period, now2 + base, | ||
1491 | base); | ||
1492 | |||
1493 | /* Try to keep the last TD intact for scanning later */ | ||
1494 | skip = span - period; | ||
1495 | |||
1496 | /* Will it come before the current scan position? */ | ||
1497 | if (empty) { | ||
1498 | skip = span; /* Skip the entire URB */ | ||
1499 | status = 1; /* and give it back immediately */ | ||
1500 | iso_sched_free(stream, sched); | ||
1501 | sched = NULL; | ||
1502 | } | ||
1503 | } | ||
1504 | urb->error_count = skip / period; | ||
1505 | if (sched) | ||
1506 | sched->first_packet = urb->error_count; | ||
1507 | goto use_start; | ||
1508 | |||
1509 | do_ASAP: | ||
1510 | /* Use the first slot after "next" */ | ||
1511 | start = next + ((start - next) & (period - 1)); | ||
1512 | |||
1513 | use_start: | ||
1482 | /* Tried to schedule too far into the future? */ | 1514 | /* Tried to schedule too far into the future? */ |
1483 | if (unlikely(start - base + span - period >= mod)) { | 1515 | if (unlikely(start + span - period >= mod + wrap)) { |
1484 | ehci_dbg(ehci, "request %p would overflow (%u+%u >= %u)\n", | 1516 | ehci_dbg(ehci, "request %p would overflow (%u+%u >= %u)\n", |
1485 | urb, start - base, span - period, mod); | 1517 | urb, start, span - period, mod + wrap); |
1486 | status = -EFBIG; | 1518 | status = -EFBIG; |
1487 | goto fail; | 1519 | goto fail; |
1488 | } | 1520 | } |
1489 | 1521 | ||
1490 | stream->next_uframe = start & (mod - 1); | 1522 | start += base; |
1523 | stream->next_uframe = (start + skip) & (mod - 1); | ||
1491 | 1524 | ||
1492 | /* report high speed start in uframes; full speed, in frames */ | 1525 | /* report high speed start in uframes; full speed, in frames */ |
1493 | urb->start_frame = stream->next_uframe; | 1526 | urb->start_frame = start & (mod - 1); |
1494 | if (!stream->highspeed) | 1527 | if (!stream->highspeed) |
1495 | urb->start_frame >>= 3; | 1528 | urb->start_frame >>= 3; |
1496 | 1529 | ||
1497 | /* Make sure scan_isoc() sees these */ | 1530 | /* Make sure scan_isoc() sees these */ |
1498 | if (ehci->isoc_count == 0) | 1531 | if (ehci->isoc_count == 0) |
1499 | ehci->last_iso_frame = now >> 3; | 1532 | ehci->last_iso_frame = now >> 3; |
1500 | return 0; | 1533 | return status; |
1501 | 1534 | ||
1502 | fail: | 1535 | fail: |
1503 | iso_sched_free(stream, sched); | 1536 | iso_sched_free(stream, sched); |
@@ -1610,7 +1643,8 @@ static void itd_link_urb( | |||
1610 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; | 1643 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; |
1611 | 1644 | ||
1612 | /* fill iTDs uframe by uframe */ | 1645 | /* fill iTDs uframe by uframe */ |
1613 | for (packet = 0, itd = NULL; packet < urb->number_of_packets; ) { | 1646 | for (packet = iso_sched->first_packet, itd = NULL; |
1647 | packet < urb->number_of_packets;) { | ||
1614 | if (itd == NULL) { | 1648 | if (itd == NULL) { |
1615 | /* ASSERT: we have all necessary itds */ | 1649 | /* ASSERT: we have all necessary itds */ |
1616 | // BUG_ON (list_empty (&iso_sched->td_list)); | 1650 | // BUG_ON (list_empty (&iso_sched->td_list)); |
@@ -1804,10 +1838,14 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, | |||
1804 | if (unlikely(status)) | 1838 | if (unlikely(status)) |
1805 | goto done_not_linked; | 1839 | goto done_not_linked; |
1806 | status = iso_stream_schedule(ehci, urb, stream); | 1840 | status = iso_stream_schedule(ehci, urb, stream); |
1807 | if (likely (status == 0)) | 1841 | if (likely(status == 0)) { |
1808 | itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); | 1842 | itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); |
1809 | else | 1843 | } else if (status > 0) { |
1844 | status = 0; | ||
1845 | ehci_urb_done(ehci, urb, 0); | ||
1846 | } else { | ||
1810 | usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); | 1847 | usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); |
1848 | } | ||
1811 | done_not_linked: | 1849 | done_not_linked: |
1812 | spin_unlock_irqrestore (&ehci->lock, flags); | 1850 | spin_unlock_irqrestore (&ehci->lock, flags); |
1813 | done: | 1851 | done: |
@@ -2008,7 +2046,7 @@ static void sitd_link_urb( | |||
2008 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; | 2046 | ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; |
2009 | 2047 | ||
2010 | /* fill sITDs frame by frame */ | 2048 | /* fill sITDs frame by frame */ |
2011 | for (packet = 0, sitd = NULL; | 2049 | for (packet = sched->first_packet, sitd = NULL; |
2012 | packet < urb->number_of_packets; | 2050 | packet < urb->number_of_packets; |
2013 | packet++) { | 2051 | packet++) { |
2014 | 2052 | ||
@@ -2178,10 +2216,14 @@ static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, | |||
2178 | if (unlikely(status)) | 2216 | if (unlikely(status)) |
2179 | goto done_not_linked; | 2217 | goto done_not_linked; |
2180 | status = iso_stream_schedule(ehci, urb, stream); | 2218 | status = iso_stream_schedule(ehci, urb, stream); |
2181 | if (status == 0) | 2219 | if (likely(status == 0)) { |
2182 | sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); | 2220 | sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); |
2183 | else | 2221 | } else if (status > 0) { |
2222 | status = 0; | ||
2223 | ehci_urb_done(ehci, urb, 0); | ||
2224 | } else { | ||
2184 | usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); | 2225 | usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); |
2226 | } | ||
2185 | done_not_linked: | 2227 | done_not_linked: |
2186 | spin_unlock_irqrestore (&ehci->lock, flags); | 2228 | spin_unlock_irqrestore (&ehci->lock, flags); |
2187 | done: | 2229 | done: |
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 291db7d09f22..2d401927e143 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h | |||
@@ -434,6 +434,7 @@ struct ehci_iso_packet { | |||
434 | struct ehci_iso_sched { | 434 | struct ehci_iso_sched { |
435 | struct list_head td_list; | 435 | struct list_head td_list; |
436 | unsigned span; | 436 | unsigned span; |
437 | unsigned first_packet; | ||
437 | struct ehci_iso_packet packet [0]; | 438 | struct ehci_iso_packet packet [0]; |
438 | }; | 439 | }; |
439 | 440 | ||