diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2011-12-22 17:05:01 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-12-22 17:05:19 -0500 |
commit | ee0db58ade2c60342a7d648f375d0a4107c39527 (patch) | |
tree | b5e2fce1dcfa281fd15427d109d5f1226de9c8c7 /drivers/usb/dwc3 | |
parent | eea9fc7ddda80d3221fd79430b841a2cb315bb9f (diff) | |
parent | eeb720fb21d61dfc3aac780e721150998ef603af (diff) |
Merge branch 'for-gadget/next' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next
* 'for-gadget/next' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb: (24 commits)
usb: dwc3: gadget: add support for SG lists
usb: dwc3: gadget: don't force 'LST' always
usb: dwc3: gadget: don't return anything on prepare trbs
usb: dwc3: gadget: re-factor dwc3_prepare_trbs()
usb: gadget: introduce support for sg lists
usb: renesas: pipe: convert a long if into a XOR operation
usb: gadget: remove useless depends on Kconfig
usb: gadget: s3c-hsudc: remove the_controller global
usb: gadget: s3c-hsudc: use release_mem_region instead of release_resource
usb: gadget: s3c-hsudc: Add regulator handling
usb: gadget: s3c-hsudc: use udc_start and udc_stop functions
usb: gadget: s3c-hsudc: move device registration to probe
usb: gadget: s3c-hsudc: add missing otg_put_transceiver in probe
usb: gadget: s3c-hsudc: add __devinit to probe function
usb: gadget: s3c-hsudc: move platform_data struct to global header
USB: EHCI: Add Marvell Host Controller driver
USB: OTG: add Marvell usb OTG driver support
usb: gadget: mv_udc: drop ARCH dependency
usb: gadget: mv_udc: fix bug in ep_dequeue
usb: gadget: enlarge maxburst bit width.
...
Diffstat (limited to 'drivers/usb/dwc3')
-rw-r--r-- | drivers/usb/dwc3/gadget.c | 239 |
1 files changed, 160 insertions, 79 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 7367e5cb9831..4c6bedad51fd 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c | |||
@@ -65,6 +65,22 @@ void dwc3_map_buffer_to_dma(struct dwc3_request *req) | |||
65 | return; | 65 | return; |
66 | } | 66 | } |
67 | 67 | ||
68 | if (req->request.num_sgs) { | ||
69 | int mapped; | ||
70 | |||
71 | mapped = dma_map_sg(dwc->dev, req->request.sg, | ||
72 | req->request.num_sgs, | ||
73 | req->direction ? DMA_TO_DEVICE | ||
74 | : DMA_FROM_DEVICE); | ||
75 | if (mapped < 0) { | ||
76 | dev_err(dwc->dev, "failed to map SGs\n"); | ||
77 | return; | ||
78 | } | ||
79 | |||
80 | req->request.num_mapped_sgs = mapped; | ||
81 | return; | ||
82 | } | ||
83 | |||
68 | if (req->request.dma == DMA_ADDR_INVALID) { | 84 | if (req->request.dma == DMA_ADDR_INVALID) { |
69 | req->request.dma = dma_map_single(dwc->dev, req->request.buf, | 85 | req->request.dma = dma_map_single(dwc->dev, req->request.buf, |
70 | req->request.length, req->direction | 86 | req->request.length, req->direction |
@@ -82,6 +98,17 @@ void dwc3_unmap_buffer_from_dma(struct dwc3_request *req) | |||
82 | return; | 98 | return; |
83 | } | 99 | } |
84 | 100 | ||
101 | if (req->request.num_mapped_sgs) { | ||
102 | req->request.dma = DMA_ADDR_INVALID; | ||
103 | dma_unmap_sg(dwc->dev, req->request.sg, | ||
104 | req->request.num_sgs, | ||
105 | req->direction ? DMA_TO_DEVICE | ||
106 | : DMA_FROM_DEVICE); | ||
107 | |||
108 | req->request.num_mapped_sgs = 0; | ||
109 | return; | ||
110 | } | ||
111 | |||
85 | if (req->mapped) { | 112 | if (req->mapped) { |
86 | dma_unmap_single(dwc->dev, req->request.dma, | 113 | dma_unmap_single(dwc->dev, req->request.dma, |
87 | req->request.length, req->direction | 114 | req->request.length, req->direction |
@@ -97,7 +124,11 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, | |||
97 | struct dwc3 *dwc = dep->dwc; | 124 | struct dwc3 *dwc = dep->dwc; |
98 | 125 | ||
99 | if (req->queued) { | 126 | if (req->queued) { |
100 | dep->busy_slot++; | 127 | if (req->request.num_mapped_sgs) |
128 | dep->busy_slot += req->request.num_mapped_sgs; | ||
129 | else | ||
130 | dep->busy_slot++; | ||
131 | |||
101 | /* | 132 | /* |
102 | * Skip LINK TRB. We can't use req->trb and check for | 133 | * Skip LINK TRB. We can't use req->trb and check for |
103 | * DWC3_TRBCTL_LINK_TRB because it points the TRB we just | 134 | * DWC3_TRBCTL_LINK_TRB because it points the TRB we just |
@@ -108,6 +139,7 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req, | |||
108 | dep->busy_slot++; | 139 | dep->busy_slot++; |
109 | } | 140 | } |
110 | list_del(&req->list); | 141 | list_del(&req->list); |
142 | req->trb = NULL; | ||
111 | 143 | ||
112 | if (req->request.status == -EINPROGRESS) | 144 | if (req->request.status == -EINPROGRESS) |
113 | req->request.status = status; | 145 | req->request.status = status; |
@@ -544,6 +576,85 @@ static void dwc3_gadget_ep_free_request(struct usb_ep *ep, | |||
544 | kfree(req); | 576 | kfree(req); |
545 | } | 577 | } |
546 | 578 | ||
579 | /** | ||
580 | * dwc3_prepare_one_trb - setup one TRB from one request | ||
581 | * @dep: endpoint for which this request is prepared | ||
582 | * @req: dwc3_request pointer | ||
583 | */ | ||
584 | static void dwc3_prepare_one_trb(struct dwc3_ep *dep, | ||
585 | struct dwc3_request *req, dma_addr_t dma, | ||
586 | unsigned length, unsigned last, unsigned chain) | ||
587 | { | ||
588 | struct dwc3 *dwc = dep->dwc; | ||
589 | struct dwc3_trb_hw *trb_hw; | ||
590 | struct dwc3_trb trb; | ||
591 | |||
592 | unsigned int cur_slot; | ||
593 | |||
594 | dev_vdbg(dwc->dev, "%s: req %p dma %08llx length %d%s%s\n", | ||
595 | dep->name, req, (unsigned long long) dma, | ||
596 | length, last ? " last" : "", | ||
597 | chain ? " chain" : ""); | ||
598 | |||
599 | trb_hw = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK]; | ||
600 | cur_slot = dep->free_slot; | ||
601 | dep->free_slot++; | ||
602 | |||
603 | /* Skip the LINK-TRB on ISOC */ | ||
604 | if (((cur_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) && | ||
605 | usb_endpoint_xfer_isoc(dep->desc)) | ||
606 | return; | ||
607 | |||
608 | memset(&trb, 0, sizeof(trb)); | ||
609 | if (!req->trb) { | ||
610 | dwc3_gadget_move_request_queued(req); | ||
611 | req->trb = trb_hw; | ||
612 | req->trb_dma = dwc3_trb_dma_offset(dep, trb_hw); | ||
613 | } | ||
614 | |||
615 | if (usb_endpoint_xfer_isoc(dep->desc)) { | ||
616 | trb.isp_imi = true; | ||
617 | trb.csp = true; | ||
618 | } else { | ||
619 | trb.chn = chain; | ||
620 | trb.lst = last; | ||
621 | } | ||
622 | |||
623 | if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable) | ||
624 | trb.sid_sofn = req->request.stream_id; | ||
625 | |||
626 | switch (usb_endpoint_type(dep->desc)) { | ||
627 | case USB_ENDPOINT_XFER_CONTROL: | ||
628 | trb.trbctl = DWC3_TRBCTL_CONTROL_SETUP; | ||
629 | break; | ||
630 | |||
631 | case USB_ENDPOINT_XFER_ISOC: | ||
632 | trb.trbctl = DWC3_TRBCTL_ISOCHRONOUS_FIRST; | ||
633 | |||
634 | /* IOC every DWC3_TRB_NUM / 4 so we can refill */ | ||
635 | if (!(cur_slot % (DWC3_TRB_NUM / 4))) | ||
636 | trb.ioc = last; | ||
637 | break; | ||
638 | |||
639 | case USB_ENDPOINT_XFER_BULK: | ||
640 | case USB_ENDPOINT_XFER_INT: | ||
641 | trb.trbctl = DWC3_TRBCTL_NORMAL; | ||
642 | break; | ||
643 | default: | ||
644 | /* | ||
645 | * This is only possible with faulty memory because we | ||
646 | * checked it already :) | ||
647 | */ | ||
648 | BUG(); | ||
649 | } | ||
650 | |||
651 | trb.length = length; | ||
652 | trb.bplh = dma; | ||
653 | trb.hwo = true; | ||
654 | |||
655 | dwc3_trb_to_hw(&trb, trb_hw); | ||
656 | } | ||
657 | |||
547 | /* | 658 | /* |
548 | * dwc3_prepare_trbs - setup TRBs from requests | 659 | * dwc3_prepare_trbs - setup TRBs from requests |
549 | * @dep: endpoint for which requests are being prepared | 660 | * @dep: endpoint for which requests are being prepared |
@@ -553,18 +664,17 @@ static void dwc3_gadget_ep_free_request(struct usb_ep *ep, | |||
553 | * transfers. The functions returns once there are not more TRBs available or | 664 | * transfers. The functions returns once there are not more TRBs available or |
554 | * it run out of requests. | 665 | * it run out of requests. |
555 | */ | 666 | */ |
556 | static struct dwc3_request *dwc3_prepare_trbs(struct dwc3_ep *dep, | 667 | static void dwc3_prepare_trbs(struct dwc3_ep *dep, bool starting) |
557 | bool starting) | ||
558 | { | 668 | { |
559 | struct dwc3_request *req, *n, *ret = NULL; | 669 | struct dwc3_request *req, *n; |
560 | struct dwc3_trb_hw *trb_hw; | ||
561 | struct dwc3_trb trb; | ||
562 | u32 trbs_left; | 670 | u32 trbs_left; |
671 | unsigned int last_one = 0; | ||
563 | 672 | ||
564 | BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM); | 673 | BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM); |
565 | 674 | ||
566 | /* the first request must not be queued */ | 675 | /* the first request must not be queued */ |
567 | trbs_left = (dep->busy_slot - dep->free_slot) & DWC3_TRB_MASK; | 676 | trbs_left = (dep->busy_slot - dep->free_slot) & DWC3_TRB_MASK; |
677 | |||
568 | /* | 678 | /* |
569 | * if busy & slot are equal than it is either full or empty. If we are | 679 | * if busy & slot are equal than it is either full or empty. If we are |
570 | * starting to proceed requests then we are empty. Otherwise we ar | 680 | * starting to proceed requests then we are empty. Otherwise we ar |
@@ -572,7 +682,7 @@ static struct dwc3_request *dwc3_prepare_trbs(struct dwc3_ep *dep, | |||
572 | */ | 682 | */ |
573 | if (!trbs_left) { | 683 | if (!trbs_left) { |
574 | if (!starting) | 684 | if (!starting) |
575 | return NULL; | 685 | return; |
576 | trbs_left = DWC3_TRB_NUM; | 686 | trbs_left = DWC3_TRB_NUM; |
577 | /* | 687 | /* |
578 | * In case we start from scratch, we queue the ISOC requests | 688 | * In case we start from scratch, we queue the ISOC requests |
@@ -596,94 +706,62 @@ static struct dwc3_request *dwc3_prepare_trbs(struct dwc3_ep *dep, | |||
596 | 706 | ||
597 | /* The last TRB is a link TRB, not used for xfer */ | 707 | /* The last TRB is a link TRB, not used for xfer */ |
598 | if ((trbs_left <= 1) && usb_endpoint_xfer_isoc(dep->desc)) | 708 | if ((trbs_left <= 1) && usb_endpoint_xfer_isoc(dep->desc)) |
599 | return NULL; | 709 | return; |
600 | 710 | ||
601 | list_for_each_entry_safe(req, n, &dep->request_list, list) { | 711 | list_for_each_entry_safe(req, n, &dep->request_list, list) { |
602 | unsigned int last_one = 0; | 712 | unsigned length; |
603 | unsigned int cur_slot; | 713 | dma_addr_t dma; |
604 | 714 | ||
605 | trb_hw = &dep->trb_pool[dep->free_slot & DWC3_TRB_MASK]; | 715 | if (req->request.num_mapped_sgs > 0) { |
606 | cur_slot = dep->free_slot; | 716 | struct usb_request *request = &req->request; |
607 | dep->free_slot++; | 717 | struct scatterlist *sg = request->sg; |
718 | struct scatterlist *s; | ||
719 | int i; | ||
608 | 720 | ||
609 | /* Skip the LINK-TRB on ISOC */ | 721 | for_each_sg(sg, s, request->num_mapped_sgs, i) { |
610 | if (((cur_slot & DWC3_TRB_MASK) == DWC3_TRB_NUM - 1) && | 722 | unsigned chain = true; |
611 | usb_endpoint_xfer_isoc(dep->desc)) | ||
612 | continue; | ||
613 | 723 | ||
614 | dwc3_gadget_move_request_queued(req); | 724 | length = sg_dma_len(s); |
615 | memset(&trb, 0, sizeof(trb)); | 725 | dma = sg_dma_address(s); |
616 | trbs_left--; | ||
617 | 726 | ||
618 | /* Is our TRB pool empty? */ | 727 | if (i == (request->num_mapped_sgs - 1) |
619 | if (!trbs_left) | 728 | || sg_is_last(s)) { |
620 | last_one = 1; | 729 | last_one = true; |
621 | /* Is this the last request? */ | 730 | chain = false; |
622 | if (list_empty(&dep->request_list)) | 731 | } |
623 | last_one = 1; | ||
624 | 732 | ||
625 | /* | 733 | trbs_left--; |
626 | * FIXME we shouldn't need to set LST bit always but we are | 734 | if (!trbs_left) |
627 | * facing some weird problem with the Hardware where it doesn't | 735 | last_one = true; |
628 | * complete even though it has been previously started. | ||
629 | * | ||
630 | * While we're debugging the problem, as a workaround to | ||
631 | * multiple TRBs handling, use only one TRB at a time. | ||
632 | */ | ||
633 | last_one = 1; | ||
634 | 736 | ||
635 | req->trb = trb_hw; | 737 | if (last_one) |
636 | if (!ret) | 738 | chain = false; |
637 | ret = req; | ||
638 | 739 | ||
639 | trb.bplh = req->request.dma; | 740 | dwc3_prepare_one_trb(dep, req, dma, length, |
741 | last_one, chain); | ||
640 | 742 | ||
641 | if (usb_endpoint_xfer_isoc(dep->desc)) { | 743 | if (last_one) |
642 | trb.isp_imi = true; | 744 | break; |
643 | trb.csp = true; | 745 | } |
644 | } else { | 746 | } else { |
645 | trb.lst = last_one; | 747 | dma = req->request.dma; |
646 | } | 748 | length = req->request.length; |
749 | trbs_left--; | ||
647 | 750 | ||
648 | if (usb_endpoint_xfer_bulk(dep->desc) && dep->stream_capable) | 751 | if (!trbs_left) |
649 | trb.sid_sofn = req->request.stream_id; | 752 | last_one = 1; |
650 | 753 | ||
651 | switch (usb_endpoint_type(dep->desc)) { | 754 | /* Is this the last request? */ |
652 | case USB_ENDPOINT_XFER_CONTROL: | 755 | if (list_is_last(&req->list, &dep->request_list)) |
653 | trb.trbctl = DWC3_TRBCTL_CONTROL_SETUP; | 756 | last_one = 1; |
654 | break; | ||
655 | 757 | ||
656 | case USB_ENDPOINT_XFER_ISOC: | 758 | dwc3_prepare_one_trb(dep, req, dma, length, |
657 | trb.trbctl = DWC3_TRBCTL_ISOCHRONOUS_FIRST; | 759 | last_one, false); |
658 | 760 | ||
659 | /* IOC every DWC3_TRB_NUM / 4 so we can refill */ | 761 | if (last_one) |
660 | if (!(cur_slot % (DWC3_TRB_NUM / 4))) | 762 | break; |
661 | trb.ioc = last_one; | ||
662 | break; | ||
663 | |||
664 | case USB_ENDPOINT_XFER_BULK: | ||
665 | case USB_ENDPOINT_XFER_INT: | ||
666 | trb.trbctl = DWC3_TRBCTL_NORMAL; | ||
667 | break; | ||
668 | default: | ||
669 | /* | ||
670 | * This is only possible with faulty memory because we | ||
671 | * checked it already :) | ||
672 | */ | ||
673 | BUG(); | ||
674 | } | 763 | } |
675 | |||
676 | trb.length = req->request.length; | ||
677 | trb.hwo = true; | ||
678 | |||
679 | dwc3_trb_to_hw(&trb, trb_hw); | ||
680 | req->trb_dma = dwc3_trb_dma_offset(dep, trb_hw); | ||
681 | |||
682 | if (last_one) | ||
683 | break; | ||
684 | } | 764 | } |
685 | |||
686 | return ret; | ||
687 | } | 765 | } |
688 | 766 | ||
689 | static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param, | 767 | static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param, |
@@ -712,11 +790,13 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep, u16 cmd_param, | |||
712 | /* req points to the first request which will be sent */ | 790 | /* req points to the first request which will be sent */ |
713 | req = next_request(&dep->req_queued); | 791 | req = next_request(&dep->req_queued); |
714 | } else { | 792 | } else { |
793 | dwc3_prepare_trbs(dep, start_new); | ||
794 | |||
715 | /* | 795 | /* |
716 | * req points to the first request where HWO changed | 796 | * req points to the first request where HWO changed |
717 | * from 0 to 1 | 797 | * from 0 to 1 |
718 | */ | 798 | */ |
719 | req = dwc3_prepare_trbs(dep, start_new); | 799 | req = next_request(&dep->req_queued); |
720 | } | 800 | } |
721 | if (!req) { | 801 | if (!req) { |
722 | dep->flags |= DWC3_EP_PENDING_REQUEST; | 802 | dep->flags |= DWC3_EP_PENDING_REQUEST; |
@@ -2093,6 +2173,7 @@ int __devinit dwc3_gadget_init(struct dwc3 *dwc) | |||
2093 | dwc->gadget.max_speed = USB_SPEED_SUPER; | 2173 | dwc->gadget.max_speed = USB_SPEED_SUPER; |
2094 | dwc->gadget.speed = USB_SPEED_UNKNOWN; | 2174 | dwc->gadget.speed = USB_SPEED_UNKNOWN; |
2095 | dwc->gadget.dev.parent = dwc->dev; | 2175 | dwc->gadget.dev.parent = dwc->dev; |
2176 | dwc->gadget.sg_supported = true; | ||
2096 | 2177 | ||
2097 | dma_set_coherent_mask(&dwc->gadget.dev, dwc->dev->coherent_dma_mask); | 2178 | dma_set_coherent_mask(&dwc->gadget.dev, dwc->dev->coherent_dma_mask); |
2098 | 2179 | ||