| From 9ee714005f246dc914cfa4f833722d24ed66ff7a Mon Sep 17 00:00:00 2001 |
| From: Madalin Bucur <madalin.bucur@nxp.com> |
| Date: Thu, 31 Oct 2019 16:37:50 +0200 |
| Subject: [PATCH] dpaa_eth: avoid timestamp read on error paths |
| |
| commit 9a4f4f3a894ff4487f5597b7aabba9432b238292 upstream. |
| |
| The dpaa_cleanup_tx_fd() function is called by the frame transmit |
| confirmation callback but also on several error paths. This function |
| is reading the transmit timestamp value. Avoid reading an invalid |
| timestamp value on the error paths. |
| |
| 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> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c |
| index 94550bceee2a..cb1694478745 100644 |
| --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c |
| +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c |
| @@ -1600,13 +1600,15 @@ static int dpaa_eth_refill_bpools(struct dpaa_priv *priv) |
| * Skb freeing is not handled here. |
| * |
| * This function may be called on error paths in the Tx function, so guard |
| - * against cases when not all fd relevant fields were filled in. |
| + * against cases when not all fd relevant fields were filled in. To avoid |
| + * reading the invalid transmission timestamp for the error paths set ts to |
| + * false. |
| * |
| * Return the skb backpointer, since for S/G frames the buffer containing it |
| * gets freed here. |
| */ |
| static struct sk_buff *dpaa_cleanup_tx_fd(const struct dpaa_priv *priv, |
| - const struct qm_fd *fd) |
| + const struct qm_fd *fd, bool ts) |
| { |
| const enum dma_data_direction dma_dir = DMA_TO_DEVICE; |
| struct device *dev = priv->net_dev->dev.parent; |
| @@ -1648,7 +1650,8 @@ static struct sk_buff *dpaa_cleanup_tx_fd(const struct dpaa_priv *priv, |
| } |
| |
| /* DMA unmapping is required before accessing the HW provided info */ |
| - if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) { |
| + if (ts && 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, |
| @@ -2116,7 +2119,7 @@ dpaa_start_xmit(struct sk_buff *skb, struct net_device *net_dev) |
| if (likely(dpaa_xmit(priv, percpu_stats, queue_mapping, &fd) == 0)) |
| return NETDEV_TX_OK; |
| |
| - dpaa_cleanup_tx_fd(priv, &fd); |
| + dpaa_cleanup_tx_fd(priv, &fd, false); |
| skb_to_fd_failed: |
| enomem: |
| percpu_stats->tx_errors++; |
| @@ -2162,7 +2165,7 @@ static void dpaa_tx_error(struct net_device *net_dev, |
| |
| percpu_priv->stats.tx_errors++; |
| |
| - skb = dpaa_cleanup_tx_fd(priv, fd); |
| + skb = dpaa_cleanup_tx_fd(priv, fd, false); |
| dev_kfree_skb(skb); |
| } |
| |
| @@ -2202,7 +2205,7 @@ static void dpaa_tx_conf(struct net_device *net_dev, |
| |
| percpu_priv->tx_confirm++; |
| |
| - skb = dpaa_cleanup_tx_fd(priv, fd); |
| + skb = dpaa_cleanup_tx_fd(priv, fd, true); |
| |
| consume_skb(skb); |
| } |
| @@ -2432,7 +2435,7 @@ static void egress_ern(struct qman_portal *portal, |
| percpu_priv->stats.tx_fifo_errors++; |
| count_ern(percpu_priv, msg); |
| |
| - skb = dpaa_cleanup_tx_fd(priv, fd); |
| + skb = dpaa_cleanup_tx_fd(priv, fd, false); |
| dev_kfree_skb_any(skb); |
| } |
| |
| -- |
| 2.7.4 |
| |