Skip to content

Commit 740f2e2

Browse files
pawellcdnsgregkh
authored andcommitted
usb: cdnsp: fix for Link TRB with TC
Stop Endpoint command on LINK TRB with TC bit set to 1 causes that internal cycle bit can have incorrect state after command complete. In consequence empty transfer ring can be incorrectly detected when EP is resumed. NOP TRB before LINK TRB avoid such scenario. Stop Endpoint command is then on NOP TRB and internal cycle bit is not changed and have correct value. Fixes: 3d82904 ("usb: cdnsp: cdns3 Add main part of Cadence USBSSP DRD Driver") cc: <stable@vger.kernel.org> Signed-off-by: Pawel Laszczak <pawell@cadence.com> Reviewed-by: Peter Chen <peter.chen@kernel.org> Link: https://lore.kernel.org/r/PH7PR07MB953878279F375CCCE6C6F40FDD8E2@PH7PR07MB9538.namprd07.prod.outlook.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent cd4897b commit 740f2e2

File tree

2 files changed

+31
-0
lines changed

2 files changed

+31
-0
lines changed

drivers/usb/cdns3/cdnsp-gadget.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,7 @@ struct cdnsp_stream_info {
811811
* generate Missed Service Error Event.
812812
* Set skip flag when receive a Missed Service Error Event and
813813
* process the missed tds on the endpoint ring.
814+
* @wa1_nop_trb: hold pointer to NOP trb.
814815
*/
815816
struct cdnsp_ep {
816817
struct usb_ep endpoint;
@@ -838,6 +839,8 @@ struct cdnsp_ep {
838839
#define EP_UNCONFIGURED BIT(7)
839840

840841
bool skip;
842+
union cdnsp_trb *wa1_nop_trb;
843+
841844
};
842845

843846
/**

drivers/usb/cdns3/cdnsp-ring.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1904,6 +1904,23 @@ int cdnsp_queue_bulk_tx(struct cdnsp_device *pdev, struct cdnsp_request *preq)
19041904
if (ret)
19051905
return ret;
19061906

1907+
/*
1908+
* workaround 1: STOP EP command on LINK TRB with TC bit set to 1
1909+
* causes that internal cycle bit can have incorrect state after
1910+
* command complete. In consequence empty transfer ring can be
1911+
* incorrectly detected when EP is resumed.
1912+
* NOP TRB before LINK TRB avoid such scenario. STOP EP command is
1913+
* then on NOP TRB and internal cycle bit is not changed and have
1914+
* correct value.
1915+
*/
1916+
if (pep->wa1_nop_trb) {
1917+
field = le32_to_cpu(pep->wa1_nop_trb->trans_event.flags);
1918+
field ^= TRB_CYCLE;
1919+
1920+
pep->wa1_nop_trb->trans_event.flags = cpu_to_le32(field);
1921+
pep->wa1_nop_trb = NULL;
1922+
}
1923+
19071924
/*
19081925
* Don't give the first TRB to the hardware (by toggling the cycle bit)
19091926
* until we've finished creating all the other TRBs. The ring's cycle
@@ -1999,6 +2016,17 @@ int cdnsp_queue_bulk_tx(struct cdnsp_device *pdev, struct cdnsp_request *preq)
19992016
send_addr = addr;
20002017
}
20012018

2019+
if (cdnsp_trb_is_link(ring->enqueue + 1)) {
2020+
field = TRB_TYPE(TRB_TR_NOOP) | TRB_IOC;
2021+
if (!ring->cycle_state)
2022+
field |= TRB_CYCLE;
2023+
2024+
pep->wa1_nop_trb = ring->enqueue;
2025+
2026+
cdnsp_queue_trb(pdev, ring, 0, 0x0, 0x0,
2027+
TRB_INTR_TARGET(0), field);
2028+
}
2029+
20022030
cdnsp_check_trb_math(preq, enqd_len);
20032031
ret = cdnsp_giveback_first_trb(pdev, pep, preq->request.stream_id,
20042032
start_cycle, start_trb);

0 commit comments

Comments
 (0)