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
This commit is contained in:
Martin Stein 2021-05-31 11:32:22 +02:00 committed by Christian Helmuth
parent 747d01e854
commit ff128df131
3 changed files with 45 additions and 1 deletions

View File

@ -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 */

View File

@ -1 +1 @@
c2dc5da56111d6a1734458679176722832b10207
8a88c22df242631ae38c2bf58d6d7b24a6fa18d1

View File

@ -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