dpaa_eth: perform DMA unmapping before read
authorMadalin Bucur <madalin.bucur@nxp.com>
Thu, 31 Oct 2019 14:37:49 +0000 (16:37 +0200)
committerDavid S. Miller <davem@davemloft.net>
Thu, 31 Oct 2019 19:13:33 +0000 (12:13 -0700)
DMA unmapping is required before accessing the HW provided timestamping
information.

Fixes: 4664856e9ca2 ("dpaa_eth: add support for hardware timestamping")
Signed-off-by: Madalin Bucur <madalin.bucur@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c

index 9979cd0..4b0a1b0 100644 (file)
@@ -1591,18 +1591,6 @@ static struct sk_buff *dpaa_cleanup_tx_fd(const struct dpaa_priv *priv,
        skbh = (struct sk_buff **)phys_to_virt(addr);
        skb = *skbh;
 
-       if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
-               memset(&shhwtstamps, 0, sizeof(shhwtstamps));
-
-               if (!fman_port_get_tstamp(priv->mac_dev->port[TX], (void *)skbh,
-                                         &ns)) {
-                       shhwtstamps.hwtstamp = ns_to_ktime(ns);
-                       skb_tstamp_tx(skb, &shhwtstamps);
-               } else {
-                       dev_warn(dev, "fman_port_get_tstamp failed!\n");
-               }
-       }
-
        if (unlikely(qm_fd_get_format(fd) == qm_fd_sg)) {
                nr_frags = skb_shinfo(skb)->nr_frags;
                dma_unmap_single(priv->tx_dma_dev, addr,
@@ -1625,14 +1613,28 @@ static struct sk_buff *dpaa_cleanup_tx_fd(const struct dpaa_priv *priv,
                        dma_unmap_page(priv->tx_dma_dev, qm_sg_addr(&sgt[i]),
                                       qm_sg_entry_get_len(&sgt[i]), dma_dir);
                }
-
-               /* Free the page frag that we allocated on Tx */
-               skb_free_frag(phys_to_virt(addr));
        } else {
                dma_unmap_single(priv->tx_dma_dev, addr,
                                 skb_tail_pointer(skb) - (u8 *)skbh, dma_dir);
        }
 
+       /* DMA unmapping is required before accessing the HW provided info */
+       if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
+               memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+
+               if (!fman_port_get_tstamp(priv->mac_dev->port[TX], (void *)skbh,
+                                         &ns)) {
+                       shhwtstamps.hwtstamp = ns_to_ktime(ns);
+                       skb_tstamp_tx(skb, &shhwtstamps);
+               } else {
+                       dev_warn(dev, "fman_port_get_tstamp failed!\n");
+               }
+       }
+
+       if (qm_fd_get_format(fd) == qm_fd_sg)
+               /* Free the page frag that we allocated on Tx */
+               skb_free_frag(phys_to_virt(addr));
+
        return skb;
 }