diff options
Diffstat (limited to 'drivers/usb/dwc3/gadget.c')
-rw-r--r-- | drivers/usb/dwc3/gadget.c | 103 |
1 files changed, 54 insertions, 49 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 58fdfad96b4d..ba444e7f9c44 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c | |||
@@ -431,15 +431,25 @@ static int dwc3_gadget_start_config(struct dwc3 *dwc, struct dwc3_ep *dep) | |||
431 | 431 | ||
432 | static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep, | 432 | static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep, |
433 | const struct usb_endpoint_descriptor *desc, | 433 | const struct usb_endpoint_descriptor *desc, |
434 | const struct usb_ss_ep_comp_descriptor *comp_desc) | 434 | const struct usb_ss_ep_comp_descriptor *comp_desc, |
435 | bool ignore) | ||
435 | { | 436 | { |
436 | struct dwc3_gadget_ep_cmd_params params; | 437 | struct dwc3_gadget_ep_cmd_params params; |
437 | 438 | ||
438 | memset(¶ms, 0x00, sizeof(params)); | 439 | memset(¶ms, 0x00, sizeof(params)); |
439 | 440 | ||
440 | params.param0 = DWC3_DEPCFG_EP_TYPE(usb_endpoint_type(desc)) | 441 | params.param0 = DWC3_DEPCFG_EP_TYPE(usb_endpoint_type(desc)) |
441 | | DWC3_DEPCFG_MAX_PACKET_SIZE(usb_endpoint_maxp(desc)) | 442 | | DWC3_DEPCFG_MAX_PACKET_SIZE(usb_endpoint_maxp(desc)); |
442 | | DWC3_DEPCFG_BURST_SIZE(dep->endpoint.maxburst - 1); | 443 | |
444 | /* Burst size is only needed in SuperSpeed mode */ | ||
445 | if (dwc->gadget.speed == USB_SPEED_SUPER) { | ||
446 | u32 burst = dep->endpoint.maxburst - 1; | ||
447 | |||
448 | params.param0 |= DWC3_DEPCFG_BURST_SIZE(burst); | ||
449 | } | ||
450 | |||
451 | if (ignore) | ||
452 | params.param0 |= DWC3_DEPCFG_IGN_SEQ_NUM; | ||
443 | 453 | ||
444 | params.param1 = DWC3_DEPCFG_XFER_COMPLETE_EN | 454 | params.param1 = DWC3_DEPCFG_XFER_COMPLETE_EN |
445 | | DWC3_DEPCFG_XFER_NOT_READY_EN; | 455 | | DWC3_DEPCFG_XFER_NOT_READY_EN; |
@@ -498,7 +508,8 @@ static int dwc3_gadget_set_xfer_resource(struct dwc3 *dwc, struct dwc3_ep *dep) | |||
498 | */ | 508 | */ |
499 | static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, | 509 | static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, |
500 | const struct usb_endpoint_descriptor *desc, | 510 | const struct usb_endpoint_descriptor *desc, |
501 | const struct usb_ss_ep_comp_descriptor *comp_desc) | 511 | const struct usb_ss_ep_comp_descriptor *comp_desc, |
512 | bool ignore) | ||
502 | { | 513 | { |
503 | struct dwc3 *dwc = dep->dwc; | 514 | struct dwc3 *dwc = dep->dwc; |
504 | u32 reg; | 515 | u32 reg; |
@@ -510,7 +521,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, | |||
510 | return ret; | 521 | return ret; |
511 | } | 522 | } |
512 | 523 | ||
513 | ret = dwc3_gadget_set_ep_config(dwc, dep, desc, comp_desc); | 524 | ret = dwc3_gadget_set_ep_config(dwc, dep, desc, comp_desc, ignore); |
514 | if (ret) | 525 | if (ret) |
515 | return ret; | 526 | return ret; |
516 | 527 | ||
@@ -558,27 +569,7 @@ static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep) | |||
558 | if (!list_empty(&dep->req_queued)) { | 569 | if (!list_empty(&dep->req_queued)) { |
559 | dwc3_stop_active_transfer(dwc, dep->number); | 570 | dwc3_stop_active_transfer(dwc, dep->number); |
560 | 571 | ||
561 | /* | 572 | /* - giveback all requests to gadget driver */ |
562 | * NOTICE: We are violating what the Databook says about the | ||
563 | * EndTransfer command. Ideally we would _always_ wait for the | ||
564 | * EndTransfer Command Completion IRQ, but that's causing too | ||
565 | * much trouble synchronizing between us and gadget driver. | ||
566 | * | ||
567 | * We have discussed this with the IP Provider and it was | ||
568 | * suggested to giveback all requests here, but give HW some | ||
569 | * extra time to synchronize with the interconnect. We're using | ||
570 | * an arbitraty 100us delay for that. | ||
571 | * | ||
572 | * Note also that a similar handling was tested by Synopsys | ||
573 | * (thanks a lot Paul) and nothing bad has come out of it. | ||
574 | * In short, what we're doing is: | ||
575 | * | ||
576 | * - Issue EndTransfer WITH CMDIOC bit set | ||
577 | * - Wait 100us | ||
578 | * - giveback all requests to gadget driver | ||
579 | */ | ||
580 | udelay(100); | ||
581 | |||
582 | while (!list_empty(&dep->req_queued)) { | 573 | while (!list_empty(&dep->req_queued)) { |
583 | req = next_request(&dep->req_queued); | 574 | req = next_request(&dep->req_queued); |
584 | 575 | ||
@@ -657,6 +648,12 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep, | |||
657 | dep = to_dwc3_ep(ep); | 648 | dep = to_dwc3_ep(ep); |
658 | dwc = dep->dwc; | 649 | dwc = dep->dwc; |
659 | 650 | ||
651 | if (dep->flags & DWC3_EP_ENABLED) { | ||
652 | dev_WARN_ONCE(dwc->dev, true, "%s is already enabled\n", | ||
653 | dep->name); | ||
654 | return 0; | ||
655 | } | ||
656 | |||
660 | switch (usb_endpoint_type(desc)) { | 657 | switch (usb_endpoint_type(desc)) { |
661 | case USB_ENDPOINT_XFER_CONTROL: | 658 | case USB_ENDPOINT_XFER_CONTROL: |
662 | strlcat(dep->name, "-control", sizeof(dep->name)); | 659 | strlcat(dep->name, "-control", sizeof(dep->name)); |
@@ -674,16 +671,10 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep, | |||
674 | dev_err(dwc->dev, "invalid endpoint transfer type\n"); | 671 | dev_err(dwc->dev, "invalid endpoint transfer type\n"); |
675 | } | 672 | } |
676 | 673 | ||
677 | if (dep->flags & DWC3_EP_ENABLED) { | ||
678 | dev_WARN_ONCE(dwc->dev, true, "%s is already enabled\n", | ||
679 | dep->name); | ||
680 | return 0; | ||
681 | } | ||
682 | |||
683 | dev_vdbg(dwc->dev, "Enabling %s\n", dep->name); | 674 | dev_vdbg(dwc->dev, "Enabling %s\n", dep->name); |
684 | 675 | ||
685 | spin_lock_irqsave(&dwc->lock, flags); | 676 | spin_lock_irqsave(&dwc->lock, flags); |
686 | ret = __dwc3_gadget_ep_enable(dep, desc, ep->comp_desc); | 677 | ret = __dwc3_gadget_ep_enable(dep, desc, ep->comp_desc, false); |
687 | spin_unlock_irqrestore(&dwc->lock, flags); | 678 | spin_unlock_irqrestore(&dwc->lock, flags); |
688 | 679 | ||
689 | return ret; | 680 | return ret; |
@@ -1087,15 +1078,10 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) | |||
1087 | * | 1078 | * |
1088 | */ | 1079 | */ |
1089 | if (dep->flags & DWC3_EP_PENDING_REQUEST) { | 1080 | if (dep->flags & DWC3_EP_PENDING_REQUEST) { |
1090 | int ret; | ||
1091 | |||
1092 | ret = __dwc3_gadget_kick_transfer(dep, 0, true); | 1081 | ret = __dwc3_gadget_kick_transfer(dep, 0, true); |
1093 | if (ret && ret != -EBUSY) { | 1082 | if (ret && ret != -EBUSY) |
1094 | struct dwc3 *dwc = dep->dwc; | ||
1095 | |||
1096 | dev_dbg(dwc->dev, "%s: failed to kick transfers\n", | 1083 | dev_dbg(dwc->dev, "%s: failed to kick transfers\n", |
1097 | dep->name); | 1084 | dep->name); |
1098 | } | ||
1099 | } | 1085 | } |
1100 | 1086 | ||
1101 | /* | 1087 | /* |
@@ -1104,16 +1090,14 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) | |||
1104 | * core may not see the modified TRB(s). | 1090 | * core may not see the modified TRB(s). |
1105 | */ | 1091 | */ |
1106 | if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && | 1092 | if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && |
1107 | (dep->flags & DWC3_EP_BUSY)) { | 1093 | (dep->flags & DWC3_EP_BUSY) && |
1094 | !(dep->flags & DWC3_EP_MISSED_ISOC)) { | ||
1108 | WARN_ON_ONCE(!dep->resource_index); | 1095 | WARN_ON_ONCE(!dep->resource_index); |
1109 | ret = __dwc3_gadget_kick_transfer(dep, dep->resource_index, | 1096 | ret = __dwc3_gadget_kick_transfer(dep, dep->resource_index, |
1110 | false); | 1097 | false); |
1111 | if (ret && ret != -EBUSY) { | 1098 | if (ret && ret != -EBUSY) |
1112 | struct dwc3 *dwc = dep->dwc; | ||
1113 | |||
1114 | dev_dbg(dwc->dev, "%s: failed to kick transfers\n", | 1099 | dev_dbg(dwc->dev, "%s: failed to kick transfers\n", |
1115 | dep->name); | 1100 | dep->name); |
1116 | } | ||
1117 | } | 1101 | } |
1118 | 1102 | ||
1119 | /* | 1103 | /* |
@@ -1518,14 +1502,14 @@ static int dwc3_gadget_start(struct usb_gadget *g, | |||
1518 | dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); | 1502 | dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); |
1519 | 1503 | ||
1520 | dep = dwc->eps[0]; | 1504 | dep = dwc->eps[0]; |
1521 | ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL); | 1505 | ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false); |
1522 | if (ret) { | 1506 | if (ret) { |
1523 | dev_err(dwc->dev, "failed to enable %s\n", dep->name); | 1507 | dev_err(dwc->dev, "failed to enable %s\n", dep->name); |
1524 | goto err0; | 1508 | goto err0; |
1525 | } | 1509 | } |
1526 | 1510 | ||
1527 | dep = dwc->eps[1]; | 1511 | dep = dwc->eps[1]; |
1528 | ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL); | 1512 | ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false); |
1529 | if (ret) { | 1513 | if (ret) { |
1530 | dev_err(dwc->dev, "failed to enable %s\n", dep->name); | 1514 | dev_err(dwc->dev, "failed to enable %s\n", dep->name); |
1531 | goto err1; | 1515 | goto err1; |
@@ -1750,7 +1734,7 @@ static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc, | |||
1750 | int i; | 1734 | int i; |
1751 | 1735 | ||
1752 | for (i = 0; i < DWC3_ENDPOINTS_NUM; i++) { | 1736 | for (i = 0; i < DWC3_ENDPOINTS_NUM; i++) { |
1753 | struct dwc3_ep *dep = dwc->eps[i]; | 1737 | dep = dwc->eps[i]; |
1754 | 1738 | ||
1755 | if (!(dep->flags & DWC3_EP_ENABLED)) | 1739 | if (!(dep->flags & DWC3_EP_ENABLED)) |
1756 | continue; | 1740 | continue; |
@@ -1877,6 +1861,25 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum) | |||
1877 | if (!dep->resource_index) | 1861 | if (!dep->resource_index) |
1878 | return; | 1862 | return; |
1879 | 1863 | ||
1864 | /* | ||
1865 | * NOTICE: We are violating what the Databook says about the | ||
1866 | * EndTransfer command. Ideally we would _always_ wait for the | ||
1867 | * EndTransfer Command Completion IRQ, but that's causing too | ||
1868 | * much trouble synchronizing between us and gadget driver. | ||
1869 | * | ||
1870 | * We have discussed this with the IP Provider and it was | ||
1871 | * suggested to giveback all requests here, but give HW some | ||
1872 | * extra time to synchronize with the interconnect. We're using | ||
1873 | * an arbitraty 100us delay for that. | ||
1874 | * | ||
1875 | * Note also that a similar handling was tested by Synopsys | ||
1876 | * (thanks a lot Paul) and nothing bad has come out of it. | ||
1877 | * In short, what we're doing is: | ||
1878 | * | ||
1879 | * - Issue EndTransfer WITH CMDIOC bit set | ||
1880 | * - Wait 100us | ||
1881 | */ | ||
1882 | |||
1880 | cmd = DWC3_DEPCMD_ENDTRANSFER; | 1883 | cmd = DWC3_DEPCMD_ENDTRANSFER; |
1881 | cmd |= DWC3_DEPCMD_HIPRI_FORCERM | DWC3_DEPCMD_CMDIOC; | 1884 | cmd |= DWC3_DEPCMD_HIPRI_FORCERM | DWC3_DEPCMD_CMDIOC; |
1882 | cmd |= DWC3_DEPCMD_PARAM(dep->resource_index); | 1885 | cmd |= DWC3_DEPCMD_PARAM(dep->resource_index); |
@@ -1884,6 +1887,8 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum) | |||
1884 | ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, ¶ms); | 1887 | ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, ¶ms); |
1885 | WARN_ON_ONCE(ret); | 1888 | WARN_ON_ONCE(ret); |
1886 | dep->resource_index = 0; | 1889 | dep->resource_index = 0; |
1890 | |||
1891 | udelay(100); | ||
1887 | } | 1892 | } |
1888 | 1893 | ||
1889 | static void dwc3_stop_active_transfers(struct dwc3 *dwc) | 1894 | static void dwc3_stop_active_transfers(struct dwc3 *dwc) |
@@ -2141,14 +2146,14 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) | |||
2141 | } | 2146 | } |
2142 | 2147 | ||
2143 | dep = dwc->eps[0]; | 2148 | dep = dwc->eps[0]; |
2144 | ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL); | 2149 | ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, true); |
2145 | if (ret) { | 2150 | if (ret) { |
2146 | dev_err(dwc->dev, "failed to enable %s\n", dep->name); | 2151 | dev_err(dwc->dev, "failed to enable %s\n", dep->name); |
2147 | return; | 2152 | return; |
2148 | } | 2153 | } |
2149 | 2154 | ||
2150 | dep = dwc->eps[1]; | 2155 | dep = dwc->eps[1]; |
2151 | ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL); | 2156 | ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, true); |
2152 | if (ret) { | 2157 | if (ret) { |
2153 | dev_err(dwc->dev, "failed to enable %s\n", dep->name); | 2158 | dev_err(dwc->dev, "failed to enable %s\n", dep->name); |
2154 | return; | 2159 | return; |