summaryrefslogtreecommitdiff
path: root/drivers/usb/dwc3/gadget.c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-07-27 13:16:18 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-07-27 13:16:18 +0200
commite98ba8cc3f8a897e4dcbf02cac5c2cf2470cd8e5 (patch)
treec5359e40f3acbbb205f163369d2e5f52bfd4f6f4 /drivers/usb/dwc3/gadget.c
parentc97793089b11f736287b65abe3d530d5ffd3857b (diff)
parentf5e46aa4a124bfac34a770c4cfe5023de99380d4 (diff)
Merge tag 'usb-for-v5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-next
Felipe writes: USB: changes for v5.9 merge window CDNS3 got several improvements, most of which are non-critical fixes. DWC3 has a reset fix for the meson platform, while dwc2 has improvements for role switch on STM32MP15 SoCs. Apart from these, we have the usual set of non-critical fixes all over the place and support for new Ingenic SoC to their PHY driver. * tag 'usb-for-v5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb: (38 commits) usb: dwc3: gadget: when the started list is empty stop the active xfer usb: dwc3: gadget: make starting isoc transfers more robust usb: dwc3: gadget: add frame number mask usb: gadget: function: printer: Interface is disabled and returns error usb: gadget: f_uac2: fix AC Interface Header Descriptor wTotalLength dt-bindings: usb: ti,keystone-dwc3.yaml: Improve schema usb: bdc: Use devm_clk_get_optional() usb: bdc: Halt controller on suspend usb: bdc: driver runs out of buffer descriptors on large ADB transfers usb: bdc: Adb shows offline after resuming from S2 bdc: Fix bug causing crash after multiple disconnects usb: bdc: Add compatible string for new style USB DT nodes dt-bindings: usb: bdc: Update compatible strings USB: PHY: JZ4770: Reformat the code to align it. USB: PHY: JZ4770: Add support for new Ingenic SoCs. USB: PHY: JZ4770: Unify code style and simplify code. dt-bindings: USB: Add bindings for new Ingenic SoCs. usb: gadget: net2280: fix memory leak on probe error handling paths usb: cdns3: drd: simplify *switch_gadet and *switch_host usb: cdns3: core: removed overwriting some error code ...
Diffstat (limited to 'drivers/usb/dwc3/gadget.c')
-rw-r--r--drivers/usb/dwc3/gadget.c30
1 files changed, 27 insertions, 3 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 3ab6f118c508..e44bfc3b5096 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1403,7 +1403,7 @@ static int dwc3_gadget_start_isoc_quirk(struct dwc3_ep *dep)
* Check if we can start isoc transfer on the next interval or
* 4 uframes in the future with BIT[15:14] as dep->combo_num
*/
- test_frame_number = dep->frame_number & 0x3fff;
+ test_frame_number = dep->frame_number & DWC3_FRNUMBER_MASK;
test_frame_number |= dep->combo_num << 14;
test_frame_number += max_t(u32, 4, dep->interval);
@@ -1450,7 +1450,7 @@ static int dwc3_gadget_start_isoc_quirk(struct dwc3_ep *dep)
else if (test0 && test1)
dep->combo_num = 0;
- dep->frame_number &= 0x3fff;
+ dep->frame_number &= DWC3_FRNUMBER_MASK;
dep->frame_number |= dep->combo_num << 14;
dep->frame_number += max_t(u32, 4, dep->interval);
@@ -1463,6 +1463,7 @@ static int dwc3_gadget_start_isoc_quirk(struct dwc3_ep *dep)
static int __dwc3_gadget_start_isoc(struct dwc3_ep *dep)
{
+ const struct usb_endpoint_descriptor *desc = dep->endpoint.desc;
struct dwc3 *dwc = dep->dwc;
int ret;
int i;
@@ -1480,6 +1481,27 @@ static int __dwc3_gadget_start_isoc(struct dwc3_ep *dep)
return dwc3_gadget_start_isoc_quirk(dep);
}
+ if (desc->bInterval <= 14 &&
+ dwc->gadget.speed >= USB_SPEED_HIGH) {
+ u32 frame = __dwc3_gadget_get_frame(dwc);
+ bool rollover = frame <
+ (dep->frame_number & DWC3_FRNUMBER_MASK);
+
+ /*
+ * frame_number is set from XferNotReady and may be already
+ * out of date. DSTS only provides the lower 14 bit of the
+ * current frame number. So add the upper two bits of
+ * frame_number and handle a possible rollover.
+ * This will provide the correct frame_number unless more than
+ * rollover has happened since XferNotReady.
+ */
+
+ dep->frame_number = (dep->frame_number & ~DWC3_FRNUMBER_MASK) |
+ frame;
+ if (rollover)
+ dep->frame_number += BIT(14);
+ }
+
for (i = 0; i < DWC3_ISOC_MAX_RETRIES; i++) {
dep->frame_number = DWC3_ALIGN_FRAME(dep, i + 1);
@@ -2716,7 +2738,9 @@ static bool dwc3_gadget_endpoint_trbs_complete(struct dwc3_ep *dep,
if (dep->flags & DWC3_EP_END_TRANSFER_PENDING)
goto out;
- if (status == -EXDEV && list_empty(&dep->started_list))
+ if (usb_endpoint_xfer_isoc(dep->endpoint.desc) &&
+ list_empty(&dep->started_list) &&
+ (list_empty(&dep->pending_list) || status == -EXDEV))
dwc3_stop_active_transfer(dep, true, true);
else if (dwc3_gadget_ep_should_continue(dep))
if (__dwc3_gadget_kick_transfer(dep) == 0)