diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/host/imx21-hcd.c | 56 |
1 files changed, 39 insertions, 17 deletions
diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c index 1be144167da4..890a41ccc5cd 100644 --- a/drivers/usb/host/imx21-hcd.c +++ b/drivers/usb/host/imx21-hcd.c | |||
@@ -390,15 +390,19 @@ static void schedule_nonisoc_etd(struct imx21 *imx21, struct urb *urb); | |||
390 | /* Endpoint now idle - release it's ETD(s) or asssign to queued request */ | 390 | /* Endpoint now idle - release it's ETD(s) or asssign to queued request */ |
391 | static void ep_idle(struct imx21 *imx21, struct ep_priv *ep_priv) | 391 | static void ep_idle(struct imx21 *imx21, struct ep_priv *ep_priv) |
392 | { | 392 | { |
393 | int etd_num; | ||
394 | int i; | 393 | int i; |
395 | 394 | ||
396 | for (i = 0; i < NUM_ISO_ETDS; i++) { | 395 | for (i = 0; i < NUM_ISO_ETDS; i++) { |
397 | etd_num = ep_priv->etd[i]; | 396 | int etd_num = ep_priv->etd[i]; |
397 | struct etd_priv *etd; | ||
398 | if (etd_num < 0) | 398 | if (etd_num < 0) |
399 | continue; | 399 | continue; |
400 | 400 | ||
401 | etd = &imx21->etd[etd_num]; | ||
401 | ep_priv->etd[i] = -1; | 402 | ep_priv->etd[i] = -1; |
403 | |||
404 | free_dmem(imx21, etd); /* for isoc */ | ||
405 | |||
402 | if (list_empty(&imx21->queue_for_etd)) { | 406 | if (list_empty(&imx21->queue_for_etd)) { |
403 | free_etd(imx21, etd_num); | 407 | free_etd(imx21, etd_num); |
404 | continue; | 408 | continue; |
@@ -576,30 +580,43 @@ static struct ep_priv *alloc_isoc_ep( | |||
576 | int i; | 580 | int i; |
577 | 581 | ||
578 | ep_priv = kzalloc(sizeof(struct ep_priv), GFP_ATOMIC); | 582 | ep_priv = kzalloc(sizeof(struct ep_priv), GFP_ATOMIC); |
579 | if (ep_priv == NULL) | 583 | if (!ep_priv) |
580 | return NULL; | 584 | return NULL; |
581 | 585 | ||
582 | /* Allocate the ETDs */ | 586 | for (i = 0; i < NUM_ISO_ETDS; i++) |
583 | for (i = 0; i < NUM_ISO_ETDS; i++) { | 587 | ep_priv->etd[i] = -1; |
584 | ep_priv->etd[i] = alloc_etd(imx21); | ||
585 | if (ep_priv->etd[i] < 0) { | ||
586 | int j; | ||
587 | dev_err(imx21->dev, "isoc: Couldn't allocate etd\n"); | ||
588 | for (j = 0; j < i; j++) | ||
589 | free_etd(imx21, ep_priv->etd[j]); | ||
590 | goto alloc_etd_failed; | ||
591 | } | ||
592 | imx21->etd[ep_priv->etd[i]].ep = ep; | ||
593 | } | ||
594 | 588 | ||
595 | INIT_LIST_HEAD(&ep_priv->td_list); | 589 | INIT_LIST_HEAD(&ep_priv->td_list); |
596 | ep_priv->ep = ep; | 590 | ep_priv->ep = ep; |
597 | ep->hcpriv = ep_priv; | 591 | ep->hcpriv = ep_priv; |
598 | return ep_priv; | 592 | return ep_priv; |
593 | } | ||
594 | |||
595 | static int alloc_isoc_etds(struct imx21 *imx21, struct ep_priv *ep_priv) | ||
596 | { | ||
597 | int i, j; | ||
598 | int etd_num; | ||
599 | |||
600 | /* Allocate the ETDs if required */ | ||
601 | for (i = 0; i < NUM_ISO_ETDS; i++) { | ||
602 | if (ep_priv->etd[i] < 0) { | ||
603 | etd_num = alloc_etd(imx21); | ||
604 | if (etd_num < 0) | ||
605 | goto alloc_etd_failed; | ||
606 | |||
607 | ep_priv->etd[i] = etd_num; | ||
608 | imx21->etd[etd_num].ep = ep_priv->ep; | ||
609 | } | ||
610 | } | ||
611 | return 0; | ||
599 | 612 | ||
600 | alloc_etd_failed: | 613 | alloc_etd_failed: |
601 | kfree(ep_priv); | 614 | dev_err(imx21->dev, "isoc: Couldn't allocate etd\n"); |
602 | return NULL; | 615 | for (j = 0; j < i; j++) { |
616 | free_etd(imx21, ep_priv->etd[j]); | ||
617 | ep_priv->etd[j] = -1; | ||
618 | } | ||
619 | return -ENOMEM; | ||
603 | } | 620 | } |
604 | 621 | ||
605 | static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd, | 622 | static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd, |
@@ -639,6 +656,10 @@ static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd, | |||
639 | ep_priv = ep->hcpriv; | 656 | ep_priv = ep->hcpriv; |
640 | } | 657 | } |
641 | 658 | ||
659 | ret = alloc_isoc_etds(imx21, ep_priv); | ||
660 | if (ret) | ||
661 | goto alloc_etd_failed; | ||
662 | |||
642 | ret = usb_hcd_link_urb_to_ep(hcd, urb); | 663 | ret = usb_hcd_link_urb_to_ep(hcd, urb); |
643 | if (ret) | 664 | if (ret) |
644 | goto link_failed; | 665 | goto link_failed; |
@@ -718,6 +739,7 @@ alloc_dmem_failed: | |||
718 | usb_hcd_unlink_urb_from_ep(hcd, urb); | 739 | usb_hcd_unlink_urb_from_ep(hcd, urb); |
719 | 740 | ||
720 | link_failed: | 741 | link_failed: |
742 | alloc_etd_failed: | ||
721 | alloc_ep_failed: | 743 | alloc_ep_failed: |
722 | spin_unlock_irqrestore(&imx21->lock, flags); | 744 | spin_unlock_irqrestore(&imx21->lock, flags); |
723 | kfree(urb_priv->isoc_td); | 745 | kfree(urb_priv->isoc_td); |