amd-xgbe: Check Rx queue fifos before stopping Rx DMA

Check to be sure that the Rx queue fifos are empty before stopping the
Rx DMA channels.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Lendacky, Thomas 2016-02-17 11:49:16 -06:00 коммит произвёл David S. Miller
Родитель b3b715974b
Коммит c3727d61ea
2 изменённых файлов: 37 добавлений и 3 удалений

Просмотреть файл

@ -6,7 +6,7 @@
*
* License 1: GPLv2
*
* Copyright (c) 2014 Advanced Micro Devices, Inc.
* Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
*
* This file is free software; you may copy, redistribute and/or modify
* it under the terms of the GNU General Public License as published by
@ -56,7 +56,7 @@
*
* License 2: Modified BSD
*
* Copyright (c) 2014 Advanced Micro Devices, Inc.
* Copyright (c) 2014-2016 Advanced Micro Devices, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -768,12 +768,16 @@
#define MTL_Q_TQDR 0x08
#define MTL_Q_RQOMR 0x40
#define MTL_Q_RQMPOCR 0x44
#define MTL_Q_RQDR 0x4c
#define MTL_Q_RQDR 0x48
#define MTL_Q_RQFCR 0x50
#define MTL_Q_IER 0x70
#define MTL_Q_ISR 0x74
/* MTL queue register entry bit positions and sizes */
#define MTL_Q_RQDR_PRXQ_INDEX 16
#define MTL_Q_RQDR_PRXQ_WIDTH 14
#define MTL_Q_RQDR_RXQSTS_INDEX 4
#define MTL_Q_RQDR_RXQSTS_WIDTH 2
#define MTL_Q_RQFCR_RFA_INDEX 1
#define MTL_Q_RQFCR_RFA_WIDTH 6
#define MTL_Q_RQFCR_RFD_INDEX 17

Просмотреть файл

@ -2656,6 +2656,32 @@ static void xgbe_disable_tx(struct xgbe_prv_data *pdata)
}
}
static void xgbe_prepare_rx_stop(struct xgbe_prv_data *pdata,
unsigned int queue)
{
unsigned int rx_status;
unsigned long rx_timeout;
/* The Rx engine cannot be stopped if it is actively processing
* packets. Wait for the Rx queue to empty the Rx fifo. Don't
* wait forever though...
*/
rx_timeout = jiffies + (XGBE_DMA_STOP_TIMEOUT * HZ);
while (time_before(jiffies, rx_timeout)) {
rx_status = XGMAC_MTL_IOREAD(pdata, queue, MTL_Q_RQDR);
if ((XGMAC_GET_BITS(rx_status, MTL_Q_RQDR, PRXQ) == 0) &&
(XGMAC_GET_BITS(rx_status, MTL_Q_RQDR, RXQSTS) == 0))
break;
usleep_range(500, 1000);
}
if (!time_before(jiffies, rx_timeout))
netdev_info(pdata->netdev,
"timed out waiting for Rx queue %u to empty\n",
queue);
}
static void xgbe_enable_rx(struct xgbe_prv_data *pdata)
{
struct xgbe_channel *channel;
@ -2694,6 +2720,10 @@ static void xgbe_disable_rx(struct xgbe_prv_data *pdata)
XGMAC_IOWRITE_BITS(pdata, MAC_RCR, ACS, 0);
XGMAC_IOWRITE_BITS(pdata, MAC_RCR, RE, 0);
/* Prepare for Rx DMA channel stop */
for (i = 0; i < pdata->rx_q_count; i++)
xgbe_prepare_rx_stop(pdata, i);
/* Disable each Rx queue */
XGMAC_IOWRITE(pdata, MAC_RQC0R, 0);