Commit 7a21b27a authored by Pawel Laszczak's avatar Pawel Laszczak Committed by Greg Kroah-Hartman
Browse files

usb: cdnsp: fix issue with ZLP - added TD_SIZE = 1



Patch modifies the TD_SIZE in TRB before ZLP TRB.
The TD_SIZE in TRB before ZLP TRB must be set to 1 to force
processing ZLP TRB by controller.

cc: <stable@vger.kernel.org>
Fixes: 3d829045 ("usb: cdnsp: cdns3 Add main part of Cadence USBSSP DRD Driver")
Signed-off-by: default avatarPawel Laszczak <pawell@cadence.com>
Reviewed-by: default avatarPeter Chen <peter.chen@kernel.org>
Link: https://lore.kernel.org/r/20221115092218.421267-1-pawell@cadence.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent f90f5afd
Loading
Loading
Loading
Loading
+10 −4
Original line number Diff line number Diff line
@@ -1763,10 +1763,15 @@ static u32 cdnsp_td_remainder(struct cdnsp_device *pdev,
			      int trb_buff_len,
			      unsigned int td_total_len,
			      struct cdnsp_request *preq,
			      bool more_trbs_coming)
			      bool more_trbs_coming,
			      bool zlp)
{
	u32 maxp, total_packet_count;

	/* Before ZLP driver needs set TD_SIZE = 1. */
	if (zlp)
		return 1;

	/* One TRB with a zero-length data packet. */
	if (!more_trbs_coming || (transferred == 0 && trb_buff_len == 0) ||
	    trb_buff_len == td_total_len)
@@ -1960,7 +1965,8 @@ int cdnsp_queue_bulk_tx(struct cdnsp_device *pdev, struct cdnsp_request *preq)
		/* Set the TRB length, TD size, and interrupter fields. */
		remainder = cdnsp_td_remainder(pdev, enqd_len, trb_buff_len,
					       full_len, preq,
					       more_trbs_coming);
					       more_trbs_coming,
					       zero_len_trb);

		length_field = TRB_LEN(trb_buff_len) | TRB_TD_SIZE(remainder) |
			TRB_INTR_TARGET(0);
@@ -2025,7 +2031,7 @@ int cdnsp_queue_ctrl_tx(struct cdnsp_device *pdev, struct cdnsp_request *preq)

	if (preq->request.length > 0) {
		remainder = cdnsp_td_remainder(pdev, 0, preq->request.length,
					       preq->request.length, preq, 1);
					       preq->request.length, preq, 1, 0);

		length_field = TRB_LEN(preq->request.length) |
				TRB_TD_SIZE(remainder) | TRB_INTR_TARGET(0);
@@ -2226,7 +2232,7 @@ static int cdnsp_queue_isoc_tx(struct cdnsp_device *pdev,
		/* Set the TRB length, TD size, & interrupter fields. */
		remainder = cdnsp_td_remainder(pdev, running_total,
					       trb_buff_len, td_len, preq,
					       more_trbs_coming);
					       more_trbs_coming, 0);

		length_field = TRB_LEN(trb_buff_len) | TRB_INTR_TARGET(0);