Skip to content

Commit 2096dde

Browse files
tmon-nordicrlubos
authored andcommitted
[nrf fromtree] drivers: udc_dwc2: Handle IN events before OUT events
DWC2 otg OUT transfers are being used for SETUP DATA0, OUT Data Stage packets and OUT Status Stage ZLP. On High-Speed it is possible for IN Data Stage, OUT Status Stage ZLP and subsequent SETUP DATA0 to happen in very quick succession, making all the three events appear at the same time to the handler thread. The handler thread is picking up next endpoint to handle based on the least significant bit set. When OUT endpoints were on bits 0-15 and IN endpoints were on bits 16-31, the least significant bit policy favored OUT endpoints over IN endpoints. This caused problems in Completer mode (but suprisingly not in Buffer DMA mode) that lead to incorrect control transfer handling. The choice between least significant bit first or most significant bit first is arbitrary. Switching from least to most significant bit first would have resolved the issue. It would also favor higher numbered endpoints over lower numbered endpoints. Swap the order of endpoints in bitmaps to have IN on bits 0-15 and OUT on bits 16-31 to keep handling lower numbered endpoints first and resolve the control transfer handling in Completer mode. Signed-off-by: Tomasz Moń <[email protected]> (cherry picked from commit 94a6b82)
1 parent ee1a57a commit 2096dde

File tree

1 file changed

+10
-10
lines changed

1 file changed

+10
-10
lines changed

drivers/usb/udc/udc_dwc2.c

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,9 @@ struct udc_dwc2_data {
9999
struct k_thread thread_data;
100100
/* Main events the driver thread waits for */
101101
struct k_event drv_evt;
102-
/* Transfer triggers (OUT on bits 0-15, IN on bits 16-31) */
102+
/* Transfer triggers (IN on bits 0-15, OUT on bits 16-31) */
103103
struct k_event xfer_new;
104-
/* Finished transactions (OUT on bits 0-15, IN on bits 16-31) */
104+
/* Finished transactions (IN on bits 0-15, OUT on bits 16-31) */
105105
struct k_event xfer_finished;
106106
struct dwc2_reg_backup backup;
107107
uint32_t ghwcfg1;
@@ -1554,9 +1554,9 @@ static int udc_dwc2_ep_clear_halt(const struct device *dev,
15541554
uint32_t ep_bit;
15551555

15561556
if (USB_EP_DIR_IS_IN(cfg->addr)) {
1557-
ep_bit = BIT(16 + USB_EP_GET_IDX(cfg->addr));
1558-
} else {
15591557
ep_bit = BIT(USB_EP_GET_IDX(cfg->addr));
1558+
} else {
1559+
ep_bit = BIT(16 + USB_EP_GET_IDX(cfg->addr));
15601560
}
15611561

15621562
k_event_post(&priv->xfer_new, ep_bit);
@@ -1579,9 +1579,9 @@ static int udc_dwc2_ep_enqueue(const struct device *dev,
15791579
uint32_t ep_bit;
15801580

15811581
if (USB_EP_DIR_IS_IN(cfg->addr)) {
1582-
ep_bit = BIT(16 + USB_EP_GET_IDX(cfg->addr));
1583-
} else {
15841582
ep_bit = BIT(USB_EP_GET_IDX(cfg->addr));
1583+
} else {
1584+
ep_bit = BIT(16 + USB_EP_GET_IDX(cfg->addr));
15851585
}
15861586

15871587
k_event_post(&priv->xfer_new, ep_bit);
@@ -2346,7 +2346,7 @@ static inline void dwc2_handle_in_xfercompl(const struct device *dev,
23462346
return;
23472347
}
23482348

2349-
k_event_post(&priv->xfer_finished, BIT(16 + ep_idx));
2349+
k_event_post(&priv->xfer_finished, BIT(ep_idx));
23502350
k_event_post(&priv->drv_evt, BIT(DWC2_DRV_EVT_EP_FINISHED));
23512351
}
23522352

@@ -2452,7 +2452,7 @@ static inline void dwc2_handle_out_xfercompl(const struct device *dev,
24522452
net_buf_tailroom(buf)) {
24532453
dwc2_prep_rx(dev, buf, ep_cfg);
24542454
} else {
2455-
k_event_post(&priv->xfer_finished, BIT(ep_idx));
2455+
k_event_post(&priv->xfer_finished, BIT(16 + ep_idx));
24562456
k_event_post(&priv->drv_evt, BIT(DWC2_DRV_EVT_EP_FINISHED));
24572457
}
24582458
}
@@ -2803,9 +2803,9 @@ static uint8_t pull_next_ep_from_bitmap(uint32_t *bitmap)
28032803
*bitmap &= ~BIT(bit);
28042804

28052805
if (bit >= 16) {
2806-
return USB_EP_DIR_IN | (bit - 16);
2806+
return USB_EP_DIR_OUT | (bit - 16);
28072807
} else {
2808-
return USB_EP_DIR_OUT | bit;
2808+
return USB_EP_DIR_IN | bit;
28092809
}
28102810
}
28112811

0 commit comments

Comments
 (0)