Skip to content

Commit 614dd57

Browse files
tmon-nordickartben
authored andcommitted
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]>
1 parent 47650a4 commit 614dd57

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
@@ -422,6 +422,11 @@ static int dwc2_ctrl_feed_dout(const struct device *dev, const size_t length)
422422
return -ENOMEM;
423423
}
424424

425+
if (dwc2_in_buffer_dma_mode(dev)) {
426+
/* Get rid of all dirty cache lines */
427+
sys_cache_data_invd_range(buf->data, net_buf_tailroom(buf));
428+
}
429+
425430
udc_buf_put(ep_cfg, buf);
426431
atomic_set_bit(&priv->xfer_new, 16);
427432
k_event_post(&priv->drv_evt, BIT(DWC2_DRV_EVT_XFER));
@@ -592,8 +597,6 @@ static int dwc2_tx_fifo_write(const struct device *dev,
592597

593598
sys_write32((uint32_t)buf->data,
594599
(mem_addr_t)&base->in_ep[ep_idx].diepdma);
595-
596-
sys_cache_data_flush_range(buf->data, len);
597600
}
598601

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

794797
sys_write32((uint32_t)data,
795798
(mem_addr_t)&base->out_ep[ep_idx].doepdma);
796-
797-
sys_cache_data_invd_range(data, xfersize);
798799
}
799800

800801
sys_write32(doepctl, doepctl_reg);
@@ -971,6 +972,10 @@ static inline int dwc2_handle_evt_dout(const struct device *dev,
971972
return -ENODATA;
972973
}
973974

975+
if (dwc2_in_buffer_dma_mode(dev)) {
976+
sys_cache_data_invd_range(buf->data, buf->len);
977+
}
978+
974979
udc_ep_set_busy(cfg, false);
975980

976981
if (cfg->addr == USB_CONTROL_EP_OUT) {
@@ -1838,6 +1843,17 @@ static int udc_dwc2_ep_enqueue(const struct device *dev,
18381843
struct udc_dwc2_data *const priv = udc_get_private(dev);
18391844

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

18431859
if (!cfg->stat.halted) {
@@ -1864,6 +1880,13 @@ static int udc_dwc2_ep_dequeue(const struct device *dev,
18641880
udc_dwc2_ep_disable(dev, cfg, false, true);
18651881

18661882
buf = udc_buf_get_all(cfg);
1883+
1884+
if (dwc2_in_buffer_dma_mode(dev) && USB_EP_DIR_IS_OUT(cfg->addr)) {
1885+
for (struct net_buf *iter = buf; iter; iter = iter->frags) {
1886+
sys_cache_data_invd_range(iter->data, iter->len);
1887+
}
1888+
}
1889+
18671890
if (buf) {
18681891
udc_submit_ep_event(dev, buf, -ECONNABORTED);
18691892
}
@@ -2830,7 +2853,9 @@ static inline void dwc2_handle_out_xfercompl(const struct device *dev,
28302853
}
28312854

28322855
if (dwc2_in_buffer_dma_mode(dev) && bcnt) {
2833-
sys_cache_data_invd_range(net_buf_tail(buf), bcnt);
2856+
/* Update just the length, cache will be invalidated in thread
2857+
* context after transfer if finished or cancelled.
2858+
*/
28342859
net_buf_add(buf, bcnt);
28352860
}
28362861

0 commit comments

Comments
 (0)