amd-xgbe: Update how to determine DMA channel status
authorLendacky, Thomas <Thomas.Lendacky@amd.com>
Thu, 3 Nov 2016 18:19:17 +0000 (13:19 -0500)
committerDavid S. Miller <davem@davemloft.net>
Fri, 4 Nov 2016 18:48:45 +0000 (14:48 -0400)
Tx and Rx DMA channel status determiniation is different depending on the
version of the hardware. Update the channel status processing code to
account for the change.  Also, reduce the timeout value used when stopping
the channels.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/amd/xgbe/xgbe-common.h
drivers/net/ethernet/amd/xgbe/xgbe-dev.c
drivers/net/ethernet/amd/xgbe/xgbe.h

index 6c40915d065ba56155cd62897e9cc32e024c0c4d..8036ee52add682a4c6f4469d87813a431e4c4b66 100644 (file)
 #define MTL_Q_RQOMR_RSF_WIDTH          1
 #define MTL_Q_RQOMR_RTC_INDEX          0
 #define MTL_Q_RQOMR_RTC_WIDTH          2
+#define MTL_Q_TQDR_TRCSTS_INDEX                1
+#define MTL_Q_TQDR_TRCSTS_WIDTH                2
+#define MTL_Q_TQDR_TXQSTS_INDEX                4
+#define MTL_Q_TQDR_TXQSTS_WIDTH                1
 #define MTL_Q_TQOMR_FTQ_INDEX          0
 #define MTL_Q_TQOMR_FTQ_WIDTH          1
 #define MTL_Q_TQOMR_Q2TCMAP_INDEX      8
index fbd60ee0260b5eb7aafe99ccf4d9d3ec3851f348..0a7ab63deaf9e1d2c53dbc5bbe248765a8b95fde 100644 (file)
@@ -2944,20 +2944,48 @@ static void xgbe_config_mmc(struct xgbe_prv_data *pdata)
        XGMAC_IOWRITE_BITS(pdata, MMC_CR, CR, 1);
 }
 
+static void xgbe_txq_prepare_tx_stop(struct xgbe_prv_data *pdata,
+                                    unsigned int queue)
+{
+       unsigned int tx_status;
+       unsigned long tx_timeout;
+
+       /* The Tx engine cannot be stopped if it is actively processing
+        * packets. Wait for the Tx queue to empty the Tx fifo.  Don't
+        * wait forever though...
+        */
+       tx_timeout = jiffies + (XGBE_DMA_STOP_TIMEOUT * HZ);
+       while (time_before(jiffies, tx_timeout)) {
+               tx_status = XGMAC_MTL_IOREAD(pdata, queue, MTL_Q_TQDR);
+               if ((XGMAC_GET_BITS(tx_status, MTL_Q_TQDR, TRCSTS) != 1) &&
+                   (XGMAC_GET_BITS(tx_status, MTL_Q_TQDR, TXQSTS) == 0))
+                       break;
+
+               usleep_range(500, 1000);
+       }
+
+       if (!time_before(jiffies, tx_timeout))
+               netdev_info(pdata->netdev,
+                           "timed out waiting for Tx queue %u to empty\n",
+                           queue);
+}
+
 static void xgbe_prepare_tx_stop(struct xgbe_prv_data *pdata,
-                                struct xgbe_channel *channel)
+                                unsigned int queue)
 {
        unsigned int tx_dsr, tx_pos, tx_qidx;
        unsigned int tx_status;
        unsigned long tx_timeout;
 
+       if (XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER) > 0x20)
+               return xgbe_txq_prepare_tx_stop(pdata, queue);
+
        /* Calculate the status register to read and the position within */
-       if (channel->queue_index < DMA_DSRX_FIRST_QUEUE) {
+       if (queue < DMA_DSRX_FIRST_QUEUE) {
                tx_dsr = DMA_DSR0;
-               tx_pos = (channel->queue_index * DMA_DSR_Q_WIDTH) +
-                        DMA_DSR0_TPS_START;
+               tx_pos = (queue * DMA_DSR_Q_WIDTH) + DMA_DSR0_TPS_START;
        } else {
-               tx_qidx = channel->queue_index - DMA_DSRX_FIRST_QUEUE;
+               tx_qidx = queue - DMA_DSRX_FIRST_QUEUE;
 
                tx_dsr = DMA_DSR1 + ((tx_qidx / DMA_DSRX_QPR) * DMA_DSRX_INC);
                tx_pos = ((tx_qidx % DMA_DSRX_QPR) * DMA_DSR_Q_WIDTH) +
@@ -2982,7 +3010,7 @@ static void xgbe_prepare_tx_stop(struct xgbe_prv_data *pdata,
        if (!time_before(jiffies, tx_timeout))
                netdev_info(pdata->netdev,
                            "timed out waiting for Tx DMA channel %u to stop\n",
-                           channel->queue_index);
+                           queue);
 }
 
 static void xgbe_enable_tx(struct xgbe_prv_data *pdata)
@@ -3014,13 +3042,8 @@ static void xgbe_disable_tx(struct xgbe_prv_data *pdata)
        unsigned int i;
 
        /* Prepare for Tx DMA channel stop */
-       channel = pdata->channel;
-       for (i = 0; i < pdata->channel_count; i++, channel++) {
-               if (!channel->tx_ring)
-                       break;
-
-               xgbe_prepare_tx_stop(pdata, channel);
-       }
+       for (i = 0; i < pdata->tx_q_count; i++)
+               xgbe_prepare_tx_stop(pdata, i);
 
        /* Disable MAC Tx */
        XGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 0);
@@ -3144,13 +3167,8 @@ static void xgbe_powerdown_tx(struct xgbe_prv_data *pdata)
        unsigned int i;
 
        /* Prepare for Tx DMA channel stop */
-       channel = pdata->channel;
-       for (i = 0; i < pdata->channel_count; i++, channel++) {
-               if (!channel->tx_ring)
-                       break;
-
-               xgbe_prepare_tx_stop(pdata, channel);
-       }
+       for (i = 0; i < pdata->tx_q_count; i++)
+               xgbe_prepare_tx_stop(pdata, i);
 
        /* Disable MAC Tx */
        XGMAC_IOWRITE_BITS(pdata, MAC_TCR, TE, 0);
index 7cbf91b4aa7942443b2ce566a0226c683866529a..d5cae1557908299cbc86c618714a38f642928658 100644 (file)
 #define XGBE_MAX_DMA_CHANNELS  16
 #define XGBE_MAX_QUEUES                16
 #define XGBE_PRIORITY_QUEUES   8
-#define XGBE_DMA_STOP_TIMEOUT  5
+#define XGBE_DMA_STOP_TIMEOUT  1
 
 /* DMA cache settings - Outer sharable, write-back, write-allocate */
 #define XGBE_DMA_OS_AXDOMAIN   0x2