net: sh_eth: Workaround cache issues
U-Boot writes to RX packets when constructing replies.
This can cause stale cached data to be written to RX
buffer while we're receiving a packet. This causes RX
packet corruption because we invalidate the cache right
before processing the packet. Invalidate packet buffer
cache when preparing RX descriptor as well. This seems
to fix RX packet drops with high RX traffic.
While at it flush the descriptors right before enabling
RX/TX in sh_eth_tx_desc_init/sh_eth_rx_desc_init callbacks
when they are ready instead of flushing after allocation.
Signed-off-by: Valentine Barshak <valentine.barshak@cogentembedded.com>
Reviewed-by: Marek Vasut <marek.vasut+renesas@mailbox.org>
Reviewed-by: Ramon Fried <rfried.dev@gmail.com>
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index 95042da..7314caa 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -142,6 +142,8 @@
{
struct sh_eth_info *port_info = ð->port_info[eth->port];
+ invalidate_cache(ADDR_TO_P2(port_info->rx_desc_cur->rd2), MAX_BUF_SIZE);
+
/* Make current descriptor available again */
if (port_info->rx_desc_cur->rd0 & RD_RDLE)
port_info->rx_desc_cur->rd0 = RD_RACT | RD_RDLE;
@@ -210,8 +212,6 @@
goto err;
}
- flush_cache_wback(port_info->tx_desc_alloc, alloc_desc_size);
-
/* Make sure we use a P2 address (non-cacheable) */
port_info->tx_desc_base =
(struct tx_desc_s *)ADDR_TO_P2((uintptr_t)port_info->tx_desc_alloc);
@@ -229,6 +229,7 @@
cur_tx_desc--;
cur_tx_desc->td0 |= TD_TDLE;
+ flush_cache_wback(port_info->tx_desc_alloc, alloc_desc_size);
/*
* Point the controller to the tx descriptor list. Must use physical
* addresses
@@ -264,8 +265,6 @@
goto err;
}
- flush_cache_wback(port_info->rx_desc_alloc, alloc_desc_size);
-
/* Make sure we use a P2 address (non-cacheable) */
port_info->rx_desc_base =
(struct rx_desc_s *)ADDR_TO_P2((uintptr_t)port_info->rx_desc_alloc);
@@ -299,6 +298,9 @@
cur_rx_desc--;
cur_rx_desc->rd0 |= RD_RDLE;
+ invalidate_cache(port_info->rx_buf_alloc, NUM_RX_DESC * MAX_BUF_SIZE);
+ flush_cache_wback(port_info->rx_desc_alloc, alloc_desc_size);
+
/* Point the controller to the rx descriptor list */
sh_eth_write(port_info, ADDR_TO_PHY(port_info->rx_desc_base), RDLAR);
#if defined(SH_ETH_TYPE_GETHER) || defined(SH_ETH_TYPE_RZ)