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:
Родитель
b3b715974b
Коммит
c3727d61ea
|
@ -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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче