diff options
author | Felipe Balbi <balbi@ti.com> | 2011-11-22 04:37:34 -0500 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2011-12-21 06:24:45 -0500 |
commit | c71fc37c191747ea1f00424e84f96c1f88e52bfc (patch) | |
tree | 446082d7f2d59e5976c8ae640ee149b1a761c439 /drivers/usb/dwc3 | |
parent | 898c60867827796f0f6f84e5de446098d776c866 (diff) |
usb: dwc3: gadget: re-factor dwc3_prepare_trbs()
In order to make it easier to add SG support,
let's split the big loop out to its own function.
Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/dwc3')
-rw-r--r-- | drivers/usb/dwc3/gadget.c | 146 |
1 files changed, 78 insertions, 68 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 580272042a33..317fc7d04694 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c | |||
@@ -539,6 +539,78 @@ static void dwc3_gadget_ep_free_request(struct usb_ep *ep, | |||
539 | kfree(req); | 539 | kfree(req); |
540 | } | 540 | } |
541 | 541 | ||
542 | /** | ||
543 | * dwc3_prepare_one_trb - setup one TRB from one request | ||
544 | * @dep: endpoint for which this request is prepared | ||
545 | * @req: dwc3_request pointer | ||
546 | */ | ||
547 | static int dwc3_prepare_one_trb(struct dwc3_ep *dep, | ||
548 | struct dwc3_request *req, unsigned last) | ||
549 | { | ||
550 | struct dwc3_trb_hw *trb_hw; | ||
551 | struct dwc3_trb trb; | ||
552 | |||
553 | unsigned int cur_slot; | ||
554 | |||
555 | trb_hw = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK]; | ||
556 | cur_slot = dep->free_slot; | ||
557 | dep->free_slot++; | ||
558 | |||
559 | /* Skip the LINK-TRB on ISOC */ | ||
560 | if (((cur_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) && | ||
561 | usb_endpoint_xfer_isoc(dep->desc)) | ||
562 | return 0; | ||
563 | |||
564 | dwc3_gadget_move_request_queued(req); | ||
565 | memset(&trb, 0, sizeof(trb)); | ||
566 | |||
567 | req->trb = trb_hw; | ||
568 | |||
569 | if (usb_endpoint_xfer_isoc(dep->desc)) { | ||
570 | trb.isp_imi = true; | ||
571 | trb.csp = true; | ||
572 | } else { | ||
573 | trb.lst = last; | ||
574 | } | ||
575 | |||
576 | if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable) | ||
577 | trb.sid_sofn = req->request.stream_id; | ||
578 | |||
579 | switch (usb_endpoint_type(dep->desc)) { | ||
580 | case USB_ENDPOINT_XFER_CONTROL: | ||
581 | trb.trbctl = DWC3_TRBCTL_CONTROL_SETUP; | ||
582 | break; | ||
583 | |||
584 | case USB_ENDPOINT_XFER_ISOC: | ||
585 | trb.trbctl = DWC3_TRBCTL_ISOCHRONOUS_FIRST; | ||
586 | |||
587 | /* IOC every DWC3_TRB_NUM / 4 so we can refill */ | ||
588 | if (!(cur_slot % (DWC3_TRB_NUM / 4))) | ||
589 | trb.ioc = last; | ||
590 | break; | ||
591 | |||
592 | case USB_ENDPOINT_XFER_BULK: | ||
593 | case USB_ENDPOINT_XFER_INT: | ||
594 | trb.trbctl = DWC3_TRBCTL_NORMAL; | ||
595 | break; | ||
596 | default: | ||
597 | /* | ||
598 | * This is only possible with faulty memory because we | ||
599 | * checked it already :) | ||
600 | */ | ||
601 | BUG(); | ||
602 | } | ||
603 | |||
604 | trb.length = req->request.length; | ||
605 | trb.bplh = req->request.dma; | ||
606 | trb.hwo = true; | ||
607 | |||
608 | dwc3_trb_to_hw(&trb, trb_hw); | ||
609 | req->trb_dma = dwc3_trb_dma_offset(dep, trb_hw); | ||
610 | |||
611 | return 0; | ||
612 | } | ||
613 | |||
542 | /* | 614 | /* |
543 | * dwc3_prepare_trbs - setup TRBs from requests | 615 | * dwc3_prepare_trbs - setup TRBs from requests |
544 | * @dep: endpoint for which requests are being prepared | 616 | * @dep: endpoint for which requests are being prepared |
@@ -552,14 +624,14 @@ static struct dwc3_request *dwc3_prepare_trbs(struct dwc3_ep *dep, | |||
552 | bool starting) | 624 | bool starting) |
553 | { | 625 | { |
554 | struct dwc3_request *req, *n, *ret = NULL; | 626 | struct dwc3_request *req, *n, *ret = NULL; |
555 | struct dwc3_trb_hw *trb_hw; | ||
556 | struct dwc3_trb trb; | ||
557 | u32 trbs_left; | 627 | u32 trbs_left; |
628 | unsigned int last_one = 0; | ||
558 | 629 | ||
559 | BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM); | 630 | BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM); |
560 | 631 | ||
561 | /* the first request must not be queued */ | 632 | /* the first request must not be queued */ |
562 | trbs_left = (dep->busy_slot - dep->free_slot) & DWC3_TRB_MASK; | 633 | trbs_left = (dep->busy_slot - dep->free_slot) & DWC3_TRB_MASK; |
634 | |||
563 | /* | 635 | /* |
564 | * if busy & slot are equal than it is either full or empty. If we are | 636 | * if busy & slot are equal than it is either full or empty. If we are |
565 | * starting to proceed requests then we are empty. Otherwise we ar | 637 | * starting to proceed requests then we are empty. Otherwise we ar |
@@ -594,25 +666,11 @@ static struct dwc3_request *dwc3_prepare_trbs(struct dwc3_ep *dep, | |||
594 | return NULL; | 666 | return NULL; |
595 | 667 | ||
596 | list_for_each_entry_safe(req, n, &dep->request_list, list) { | 668 | list_for_each_entry_safe(req, n, &dep->request_list, list) { |
597 | unsigned int last_one = 0; | ||
598 | unsigned int cur_slot; | ||
599 | |||
600 | trb_hw = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK]; | ||
601 | cur_slot = dep->free_slot; | ||
602 | dep->free_slot++; | ||
603 | |||
604 | /* Skip the LINK-TRB on ISOC */ | ||
605 | if (((cur_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) && | ||
606 | usb_endpoint_xfer_isoc(dep->desc)) | ||
607 | continue; | ||
608 | |||
609 | dwc3_gadget_move_request_queued(req); | ||
610 | memset(&trb, 0, sizeof(trb)); | ||
611 | trbs_left--; | 669 | trbs_left--; |
612 | 670 | ||
613 | /* Is our TRB pool empty? */ | ||
614 | if (!trbs_left) | 671 | if (!trbs_left) |
615 | last_one = 1; | 672 | last_one = 1; |
673 | |||
616 | /* Is this the last request? */ | 674 | /* Is this the last request? */ |
617 | if (list_empty(&dep->request_list)) | 675 | if (list_empty(&dep->request_list)) |
618 | last_one = 1; | 676 | last_one = 1; |
@@ -625,57 +683,9 @@ static struct dwc3_request *dwc3_prepare_trbs(struct dwc3_ep *dep, | |||
625 | * While we're debugging the problem, as a workaround to | 683 | * While we're debugging the problem, as a workaround to |
626 | * multiple TRBs handling, use only one TRB at a time. | 684 | * multiple TRBs handling, use only one TRB at a time. |
627 | */ | 685 | */ |
628 | last_one = 1; | 686 | dwc3_prepare_one_trb(dep, req, true); |
629 | 687 | ret = req; | |
630 | req->trb = trb_hw; | 688 | break; |
631 | if (!ret) | ||
632 | ret = req; | ||
633 | |||
634 | trb.bplh = req->request.dma; | ||
635 | |||
636 | if (usb_endpoint_xfer_isoc(dep->desc)) { | ||
637 | trb.isp_imi = true; | ||
638 | trb.csp = true; | ||
639 | } else { | ||
640 | trb.lst = last_one; | ||
641 | } | ||
642 | |||
643 | if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable) | ||
644 | trb.sid_sofn = req->request.stream_id; | ||
645 | |||
646 | switch (usb_endpoint_type(dep->desc)) { | ||
647 | case USB_ENDPOINT_XFER_CONTROL: | ||
648 | trb.trbctl = DWC3_TRBCTL_CONTROL_SETUP; | ||
649 | break; | ||
650 | |||
651 | case USB_ENDPOINT_XFER_ISOC: | ||
652 | trb.trbctl = DWC3_TRBCTL_ISOCHRONOUS_FIRST; | ||
653 | |||
654 | /* IOC every DWC3_TRB_NUM / 4 so we can refill */ | ||
655 | if (!(cur_slot % (DWC3_TRB_NUM / 4))) | ||
656 | trb.ioc = last_one; | ||
657 | break; | ||
658 | |||
659 | case USB_ENDPOINT_XFER_BULK: | ||
660 | case USB_ENDPOINT_XFER_INT: | ||
661 | trb.trbctl = DWC3_TRBCTL_NORMAL; | ||
662 | break; | ||
663 | default: | ||
664 | /* | ||
665 | * This is only possible with faulty memory because we | ||
666 | * checked it already :) | ||
667 | */ | ||
668 | BUG(); | ||
669 | } | ||
670 | |||
671 | trb.length = req->request.length; | ||
672 | trb.hwo = true; | ||
673 | |||
674 | dwc3_trb_to_hw(&trb, trb_hw); | ||
675 | req->trb_dma = dwc3_trb_dma_offset(dep, trb_hw); | ||
676 | |||
677 | if (last_one) | ||
678 | break; | ||
679 | } | 689 | } |
680 | 690 | ||
681 | return ret; | 691 | return ret; |