summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorValentine Barshak <valentine.barshak@cogentembedded.com>2023-05-31 01:51:30 +0300
committerMarek Vasut <marek.vasut+renesas@mailbox.org>2023-06-10 14:34:05 +0300
commitd49ba9c8d70c30d6f009e069cf43b4817be3546d (patch)
tree862e89b75099da8dd6086e96f19e7b6882c0ceac
parent92c312c734f5193205dd170a01ae4192f67a2ee5 (diff)
downloadu-boot-d49ba9c8d70c30d6f009e069cf43b4817be3546d.tar.xz
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>
-rw-r--r--drivers/net/sh_eth.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index 95042daade..7314caadfd 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -142,6 +142,8 @@ static void sh_eth_recv_finish(struct sh_eth_dev *eth)
{
struct sh_eth_info *port_info = &eth->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 @@ static int sh_eth_tx_desc_init(struct sh_eth_dev *eth)
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 @@ static int sh_eth_tx_desc_init(struct sh_eth_dev *eth)
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 @@ static int sh_eth_rx_desc_init(struct sh_eth_dev *eth)
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 @@ static int sh_eth_rx_desc_init(struct sh_eth_dev *eth)
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)