From ff128df1319e651d6339746119bfa14e6f5c77fa Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Mon, 31 May 2021 11:32:22 +0200 Subject: [PATCH] dde_linux/fec: fix unsynchronized TX DMA write Unfortunately, our current implementation of 'wmb()' doesn't seem to do what we want it to do. On base-hw + imx6q_sabrelite, the write of bdp->cbd_sc seems to get re-ordered after the write to txq->bd.reg_desc_active in the transmission path of the contrib code. Due to this, the transmission of the packet is only triggered the next time a packet is sent. However, we only quick-fix it by enforcing the execution of the write with a volatile global read as we will soon update the FEC NIC port with a new DDE approach anyway. Fixes #4010 --- .../patches/fec_tx_sync_dma_write.patch | 43 +++++++++++++++++++ repos/dde_linux/ports/dde_linux.hash | 2 +- repos/dde_linux/ports/dde_linux.port | 1 + 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 repos/dde_linux/patches/fec_tx_sync_dma_write.patch diff --git a/repos/dde_linux/patches/fec_tx_sync_dma_write.patch b/repos/dde_linux/patches/fec_tx_sync_dma_write.patch new file mode 100644 index 0000000000..e7e00c2598 --- /dev/null +++ b/repos/dde_linux/patches/fec_tx_sync_dma_write.patch @@ -0,0 +1,43 @@ +diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c +index 3f72629..2b54f2b 100644 +--- a/drivers/net/ethernet/freescale/fec_main.c ++++ b/drivers/net/ethernet/freescale/fec_main.c +@@ -428,7 +428,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, + { + struct fec_enet_private *fep = netdev_priv(ndev); + int nr_frags = skb_shinfo(skb)->nr_frags; +- struct bufdesc *bdp, *last_bdp; ++ struct bufdesc *bdp, *last_bdp, *dummy_bdp; + void *bufaddr; + dma_addr_t addr; + unsigned short status; +@@ -532,6 +532,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, + */ + status |= (BD_ENET_TX_READY | BD_ENET_TX_TC); + bdp->cbd_sc = cpu_to_fec16(status); ++ dummy_bdp = bdp; + + /* If this was the last BD in the ring, start at the beginning again. */ + bdp = fec_enet_get_nextdesc(last_bdp, &txq->bd); +@@ -542,6 +543,21 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq, + * txq->bd.cur. + */ + wmb(); ++ ++ /* ++ * Unfortunately, our current implementation of 'wmb()' doesn't seem ++ * to do what we want it to do. On base-hw + imx6q_sabrelite, the ++ * write of bdp->cbd_sc seems to get re-ordered after the write to ++ * txq->bd.reg_desc_active and, therefore, the transmission of the packet ++ * would only be triggered the next time we reach this point, ++ * i.e. when the next packet is sent. However, we only quick-fix it by ++ * enforcing the write with this volatile global read as we will ++ * soon update the FEC NIC port with a new DDE approach anyway ++ * (See Genode Github issue #4010). ++ */ ++ static unsigned long volatile dummy_cbd_sc; ++ dummy_cbd_sc = *(unsigned long volatile *)&dummy_bdp->cbd_sc; ++ + txq->bd.cur = bdp; + + /* Trigger transmission start */ diff --git a/repos/dde_linux/ports/dde_linux.hash b/repos/dde_linux/ports/dde_linux.hash index 862241b722..8b4c3143ed 100644 --- a/repos/dde_linux/ports/dde_linux.hash +++ b/repos/dde_linux/ports/dde_linux.hash @@ -1 +1 @@ -c2dc5da56111d6a1734458679176722832b10207 +8a88c22df242631ae38c2bf58d6d7b24a6fa18d1 diff --git a/repos/dde_linux/ports/dde_linux.port b/repos/dde_linux/ports/dde_linux.port index f55d7a563e..3784128327 100644 --- a/repos/dde_linux/ports/dde_linux.port +++ b/repos/dde_linux/ports/dde_linux.port @@ -211,6 +211,7 @@ PATCH_OPT(patches/intel_fb_hotplug.patch) := -p1 -d$(SRC_DIR_INTEL_FB) # Freescale NIC PATCH_OPT(patches/fec_skbuff_cast.patch) := -p1 -d$(SRC_DIR_FEC) PATCH_OPT(patches/fec_tx_bounce_dma.patch) := -p1 -d$(SRC_DIR_FEC) +PATCH_OPT(patches/fec_tx_sync_dma_write.patch) := -p1 -d$(SRC_DIR_FEC) PATCH_OPT(patches/fec_ndev_owner.patch) := -p1 -d$(SRC_DIR_FEC) # Freescale i.MX8 framebuffer