stmmac: optimize tx clean function
authorFabrice Gasnier <fabrice.gasnier@st.com>
Mon, 29 Feb 2016 13:27:36 +0000 (14:27 +0100)
committerDavid S. Miller <davem@davemloft.net>
Wed, 2 Mar 2016 19:21:32 +0000 (14:21 -0500)
This patch "inline" get_tx_owner and get_ls routines. It Results in a
unique read to tdes0, instead of three, to check TX_OWN and LS bits,
and other status bits.

It helps improve driver TX path by removing two uncached read/writes
inside TX clean loop for enhanced descriptors but not for normal ones
because the des1 must be read in any case.

Signed-off-by: Fabrice Gasnier <fabrice.gasnier@st.com>
Acked-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: Alexandre TORGUE <alexandre.torgue@st.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/stmicro/stmmac/common.h
drivers/net/ethernet/stmicro/stmmac/enh_desc.c
drivers/net/ethernet/stmicro/stmmac/norm_desc.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c

index 885c0f9808b61f3e3ba60b2995e37ede964f7a25..7ccb147710fde3e0b6bcd0fe15d20f4dacf08bd2 100644 (file)
@@ -245,6 +245,14 @@ enum rx_frame_status {
        dma_own = 0x8,
 };
 
+/* Tx status */
+enum tx_frame_status {
+       tx_done = 0x0,
+       tx_not_ls = 0x1,
+       tx_err = 0x2,
+       tx_dma_own = 0x4,
+};
+
 enum dma_irq_status {
        tx_hard_error = 0x1,
        tx_hard_error_bump_tc = 0x2,
index 1abd80ed09f363d0079e5d79e770a71af67fbaed..957610b72ace9f9c0c297aa4330229a734d59874 100644 (file)
@@ -31,7 +31,15 @@ static int enh_desc_get_tx_status(void *data, struct stmmac_extra_stats *x,
 {
        struct net_device_stats *stats = (struct net_device_stats *)data;
        unsigned int tdes0 = p->des0;
-       int ret = 0;
+       int ret = tx_done;
+
+       /* Get tx owner first */
+       if (unlikely(tdes0 & ETDES0_OWN))
+               return tx_dma_own;
+
+       /* Verify tx error by looking at the last segment. */
+       if (likely(!(tdes0 & ETDES0_LAST_SEGMENT)))
+               return tx_not_ls;
 
        if (unlikely(tdes0 & ETDES0_ERROR_SUMMARY)) {
                if (unlikely(tdes0 & ETDES0_JABBER_TIMEOUT))
@@ -71,7 +79,7 @@ static int enh_desc_get_tx_status(void *data, struct stmmac_extra_stats *x,
                        dwmac_dma_flush_tx_fifo(ioaddr);
                }
 
-               ret = -1;
+               ret = tx_err;
        }
 
        if (unlikely(tdes0 & ETDES0_DEFERRED))
index 19cc12dd0f173e99dfaf8c73ed6507d0fe8b77da..122fb5ad234b0a1e01a00f2ae5ddb2a5979478d0 100644 (file)
@@ -31,7 +31,16 @@ static int ndesc_get_tx_status(void *data, struct stmmac_extra_stats *x,
 {
        struct net_device_stats *stats = (struct net_device_stats *)data;
        unsigned int tdes0 = p->des0;
-       int ret = 0;
+       unsigned int tdes1 = p->des1;
+       int ret = tx_done;
+
+       /* Get tx owner first */
+       if (unlikely(tdes0 & TDES0_OWN))
+               return tx_dma_own;
+
+       /* Verify tx error by looking at the last segment. */
+       if (likely(!(tdes1 & TDES1_LAST_SEGMENT)))
+               return tx_not_ls;
 
        if (unlikely(tdes0 & TDES0_ERROR_SUMMARY)) {
                if (unlikely(tdes0 & TDES0_UNDERFLOW_ERROR)) {
@@ -54,7 +63,7 @@ static int ndesc_get_tx_status(void *data, struct stmmac_extra_stats *x,
                        collisions = (tdes0 & TDES0_COLLISION_COUNT_MASK) >> 3;
                        stats->collisions += collisions;
                }
-               ret = -1;
+               ret = tx_err;
        }
 
        if (tdes0 & TDES0_VLAN_FRAME)
index 24c36084e3f5d8fef23dfe30f6612d484aff0be8..d31179f597a8875bbfdcd0b0f3715213e857dabe 100644 (file)
@@ -1313,32 +1313,31 @@ static void stmmac_tx_clean(struct stmmac_priv *priv)
        priv->xstats.tx_clean++;
 
        while (entry != priv->cur_tx) {
-               int last;
                struct sk_buff *skb = priv->tx_skbuff[entry];
                struct dma_desc *p;
+               int status;
 
                if (priv->extend_desc)
                        p = (struct dma_desc *)(priv->dma_etx + entry);
                else
                        p = priv->dma_tx + entry;
 
-               /* Check if the descriptor is owned by the DMA. */
-               if (priv->hw->desc->get_tx_owner(p))
-                       break;
-
-               /* Verify tx error by looking at the last segment. */
-               last = priv->tx_skbuff_dma[entry].last_segment;
-               if (likely(last)) {
-                       int tx_error =
-                           priv->hw->desc->tx_status(&priv->dev->stats,
+               status = priv->hw->desc->tx_status(&priv->dev->stats,
                                                      &priv->xstats, p,
                                                      priv->ioaddr);
-                       if (likely(tx_error == 0)) {
+               /* Check if the descriptor is owned by the DMA */
+               if (unlikely(status & tx_dma_own))
+                       break;
+
+               /* Just consider the last segment and ...*/
+               if (likely(!(status & tx_not_ls))) {
+                       /* ... verify the status error condition */
+                       if (unlikely(status & tx_err)) {
+                               priv->dev->stats.tx_errors++;
+                       } else {
                                priv->dev->stats.tx_packets++;
                                priv->xstats.tx_pkt_n++;
-                       } else
-                               priv->dev->stats.tx_errors++;
-
+                       }
                        stmmac_get_tx_hwtstamp(priv, entry, skb);
                }
                if (netif_msg_tx_done(priv))
This page took 0.038978 seconds and 5 git commands to generate.