Skip to content

Commit b2c586e

Browse files
Minas Harutyunyanfelipebalbi
Minas Harutyunyan
authored andcommitted
usb: dwc2: Fix INTR OUT transfers in DDMA mode.
In DDMA mode if INTR OUT transfers mps not multiple of 4 then single packet corresponds to single descriptor. Descriptor limit set to mps and desc chain limit set to mps * MAX_DMA_DESC_NUM_GENERIC. On that descriptors complete, to calculate transfer size should be considered correction value for each descriptor. In start request function, if "continue" is true then dma buffer address should be incremmented by offset for all type of transfers, not only for Control DATA_OUT transfers. Fixes: cf77b5f ("usb: dwc2: gadget: Transfer length limit checking for DDMA") Fixes: e02f9aa ("usb: dwc2: gadget: EP 0 specific DDMA programming") Fixes: aa3e8bc ("usb: dwc2: gadget: DDMA transfer start and complete") Signed-off-by: Minas Harutyunyan <[email protected]> Signed-off-by: Felipe Balbi <[email protected]>
1 parent d58ba48 commit b2c586e

File tree

1 file changed

+33
-7
lines changed

1 file changed

+33
-7
lines changed

drivers/usb/dwc2/gadget.c

+33-7
Original file line numberDiff line numberDiff line change
@@ -713,8 +713,11 @@ static u32 dwc2_hsotg_read_frameno(struct dwc2_hsotg *hsotg)
713713
*/
714714
static unsigned int dwc2_gadget_get_chain_limit(struct dwc2_hsotg_ep *hs_ep)
715715
{
716+
const struct usb_endpoint_descriptor *ep_desc = hs_ep->ep.desc;
716717
int is_isoc = hs_ep->isochronous;
717718
unsigned int maxsize;
719+
u32 mps = hs_ep->ep.maxpacket;
720+
int dir_in = hs_ep->dir_in;
718721

719722
if (is_isoc)
720723
maxsize = (hs_ep->dir_in ? DEV_DMA_ISOC_TX_NBYTES_LIMIT :
@@ -723,6 +726,11 @@ static unsigned int dwc2_gadget_get_chain_limit(struct dwc2_hsotg_ep *hs_ep)
723726
else
724727
maxsize = DEV_DMA_NBYTES_LIMIT * MAX_DMA_DESC_NUM_GENERIC;
725728

729+
/* Interrupt OUT EP with mps not multiple of 4 */
730+
if (hs_ep->index)
731+
if (usb_endpoint_xfer_int(ep_desc) && !dir_in && (mps % 4))
732+
maxsize = mps * MAX_DMA_DESC_NUM_GENERIC;
733+
726734
return maxsize;
727735
}
728736

@@ -738,11 +746,14 @@ static unsigned int dwc2_gadget_get_chain_limit(struct dwc2_hsotg_ep *hs_ep)
738746
* Isochronous - descriptor rx/tx bytes bitfield limit,
739747
* Control In/Bulk/Interrupt - multiple of mps. This will allow to not
740748
* have concatenations from various descriptors within one packet.
749+
* Interrupt OUT - if mps not multiple of 4 then a single packet corresponds
750+
* to a single descriptor.
741751
*
742752
* Selects corresponding mask for RX/TX bytes as well.
743753
*/
744754
static u32 dwc2_gadget_get_desc_params(struct dwc2_hsotg_ep *hs_ep, u32 *mask)
745755
{
756+
const struct usb_endpoint_descriptor *ep_desc = hs_ep->ep.desc;
746757
u32 mps = hs_ep->ep.maxpacket;
747758
int dir_in = hs_ep->dir_in;
748759
u32 desc_size = 0;
@@ -766,6 +777,13 @@ static u32 dwc2_gadget_get_desc_params(struct dwc2_hsotg_ep *hs_ep, u32 *mask)
766777
desc_size -= desc_size % mps;
767778
}
768779

780+
/* Interrupt OUT EP with mps not multiple of 4 */
781+
if (hs_ep->index)
782+
if (usb_endpoint_xfer_int(ep_desc) && !dir_in && (mps % 4)) {
783+
desc_size = mps;
784+
*mask = DEV_DMA_NBYTES_MASK;
785+
}
786+
769787
return desc_size;
770788
}
771789

@@ -1123,13 +1141,7 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
11231141
length += (mps - (length % mps));
11241142
}
11251143

1126-
/*
1127-
* If more data to send, adjust DMA for EP0 out data stage.
1128-
* ureq->dma stays unchanged, hence increment it by already
1129-
* passed passed data count before starting new transaction.
1130-
*/
1131-
if (!index && hsotg->ep0_state == DWC2_EP0_DATA_OUT &&
1132-
continuing)
1144+
if (continuing)
11331145
offset = ureq->actual;
11341146

11351147
/* Fill DDMA chain entries */
@@ -2320,22 +2332,36 @@ static void dwc2_hsotg_change_ep_iso_parity(struct dwc2_hsotg *hsotg,
23202332
*/
23212333
static unsigned int dwc2_gadget_get_xfersize_ddma(struct dwc2_hsotg_ep *hs_ep)
23222334
{
2335+
const struct usb_endpoint_descriptor *ep_desc = hs_ep->ep.desc;
23232336
struct dwc2_hsotg *hsotg = hs_ep->parent;
23242337
unsigned int bytes_rem = 0;
2338+
unsigned int bytes_rem_correction = 0;
23252339
struct dwc2_dma_desc *desc = hs_ep->desc_list;
23262340
int i;
23272341
u32 status;
2342+
u32 mps = hs_ep->ep.maxpacket;
2343+
int dir_in = hs_ep->dir_in;
23282344

23292345
if (!desc)
23302346
return -EINVAL;
23312347

2348+
/* Interrupt OUT EP with mps not multiple of 4 */
2349+
if (hs_ep->index)
2350+
if (usb_endpoint_xfer_int(ep_desc) && !dir_in && (mps % 4))
2351+
bytes_rem_correction = 4 - (mps % 4);
2352+
23322353
for (i = 0; i < hs_ep->desc_count; ++i) {
23332354
status = desc->status;
23342355
bytes_rem += status & DEV_DMA_NBYTES_MASK;
2356+
bytes_rem -= bytes_rem_correction;
23352357

23362358
if (status & DEV_DMA_STS_MASK)
23372359
dev_err(hsotg->dev, "descriptor %d closed with %x\n",
23382360
i, status & DEV_DMA_STS_MASK);
2361+
2362+
if (status & DEV_DMA_L)
2363+
break;
2364+
23392365
desc++;
23402366
}
23412367

0 commit comments

Comments
 (0)