Skip to content

Commit a3d02e2

Browse files
tmon-nordicrlubos
authored andcommitted
[nrf fromtree] drivers: usb: dwc2: Do cache operations on ownership change
Perform cache operations in thread context when the buffer ownership changes between USB stack and UDC driver. This offers clearly measurable throughput increase on Mass Storage when double buffering is enabled. When endpoint operations are not double buffered the difference is negligible. The positive side effect is reducing number of operations performed in interrupt context. Signed-off-by: Tomasz Moń <[email protected]> (cherry picked from commit 614dd57)
1 parent 0efb854 commit a3d02e2

File tree

1 file changed

+30
-5
lines changed

1 file changed

+30
-5
lines changed

drivers/usb/udc/udc_dwc2.c

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,11 @@ static int dwc2_ctrl_feed_dout(const struct device *dev, const size_t length)
419419
return -ENOMEM;
420420
}
421421

422+
if (dwc2_in_buffer_dma_mode(dev)) {
423+
/* Get rid of all dirty cache lines */
424+
sys_cache_data_invd_range(buf->data, net_buf_tailroom(buf));
425+
}
426+
422427
udc_buf_put(ep_cfg, buf);
423428
atomic_set_bit(&priv->xfer_new, 16);
424429
k_event_post(&priv->drv_evt, BIT(DWC2_DRV_EVT_XFER));
@@ -589,8 +594,6 @@ static int dwc2_tx_fifo_write(const struct device *dev,
589594

590595
sys_write32((uint32_t)buf->data,
591596
(mem_addr_t)&base->in_ep[ep_idx].diepdma);
592-
593-
sys_cache_data_flush_range(buf->data, len);
594597
}
595598

596599
diepctl = sys_read32(diepctl_reg);
@@ -790,8 +793,6 @@ static void dwc2_prep_rx(const struct device *dev, struct net_buf *buf,
790793

791794
sys_write32((uint32_t)data,
792795
(mem_addr_t)&base->out_ep[ep_idx].doepdma);
793-
794-
sys_cache_data_invd_range(data, xfersize);
795796
}
796797

797798
sys_write32(doepctl, doepctl_reg);
@@ -968,6 +969,10 @@ static inline int dwc2_handle_evt_dout(const struct device *dev,
968969
return -ENODATA;
969970
}
970971

972+
if (dwc2_in_buffer_dma_mode(dev)) {
973+
sys_cache_data_invd_range(buf->data, buf->len);
974+
}
975+
971976
udc_ep_set_busy(cfg, false);
972977

973978
if (cfg->addr == USB_CONTROL_EP_OUT) {
@@ -1835,6 +1840,17 @@ static int udc_dwc2_ep_enqueue(const struct device *dev,
18351840
struct udc_dwc2_data *const priv = udc_get_private(dev);
18361841

18371842
LOG_DBG("%p enqueue %x %p", dev, cfg->addr, buf);
1843+
1844+
if (dwc2_in_buffer_dma_mode(dev)) {
1845+
if (USB_EP_DIR_IS_IN(cfg->addr)) {
1846+
/* Write all dirty cache lines to memory */
1847+
sys_cache_data_flush_range(buf->data, buf->len);
1848+
} else {
1849+
/* Get rid of all dirty cache lines */
1850+
sys_cache_data_invd_range(buf->data, net_buf_tailroom(buf));
1851+
}
1852+
}
1853+
18381854
udc_buf_put(cfg, buf);
18391855

18401856
if (!cfg->stat.halted) {
@@ -1861,6 +1877,13 @@ static int udc_dwc2_ep_dequeue(const struct device *dev,
18611877
udc_dwc2_ep_disable(dev, cfg, false, true);
18621878

18631879
buf = udc_buf_get_all(cfg);
1880+
1881+
if (dwc2_in_buffer_dma_mode(dev) && USB_EP_DIR_IS_OUT(cfg->addr)) {
1882+
for (struct net_buf *iter = buf; iter; iter = iter->frags) {
1883+
sys_cache_data_invd_range(iter->data, iter->len);
1884+
}
1885+
}
1886+
18641887
if (buf) {
18651888
udc_submit_ep_event(dev, buf, -ECONNABORTED);
18661889
}
@@ -2821,7 +2844,9 @@ static inline void dwc2_handle_out_xfercompl(const struct device *dev,
28212844
}
28222845

28232846
if (dwc2_in_buffer_dma_mode(dev) && bcnt) {
2824-
sys_cache_data_invd_range(net_buf_tail(buf), bcnt);
2847+
/* Update just the length, cache will be invalidated in thread
2848+
* context after transfer if finished or cancelled.
2849+
*/
28252850
net_buf_add(buf, bcnt);
28262851
}
28272852

0 commit comments

Comments
 (0)