Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c3727d61 authored by Lendacky, Thomas's avatar Lendacky, Thomas Committed by David S. Miller
Browse files

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: default avatarTom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b3b71597
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -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
+30 −0
Original line number Diff line number Diff line
@@ -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);