aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/imx21-hcd.c56
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 */
391static void ep_idle(struct imx21 *imx21, struct ep_priv *ep_priv) 391static 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
595static 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
600alloc_etd_failed: 613alloc_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
605static int imx21_hc_urb_enqueue_isoc(struct usb_hcd *hcd, 622static 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
720link_failed: 741link_failed:
742alloc_etd_failed:
721alloc_ep_failed: 743alloc_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);