aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/dwc3/gadget.c146
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 */
547static 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;