Add patches for linux-5.4. The patches are from NXP LSDK-20.04 release which was tagged LSDK-20.04-V5.4. https://source.codeaurora.org/external/qoriq/qoriq-components/linux/ For boards LS1021A-IOT, and Traverse-LS1043 which are not involved in LSDK, port the dts patches from 4.14. The patches are sorted into the following categories: 301-arch-xxxx 302-dts-xxxx 303-core-xxxx 701-net-xxxx 801-audio-xxxx 802-can-xxxx 803-clock-xxxx 804-crypto-xxxx 805-display-xxxx 806-dma-xxxx 807-gpio-xxxx 808-i2c-xxxx 809-jailhouse-xxxx 810-keys-xxxx 811-kvm-xxxx 812-pcie-xxxx 813-pm-xxxx 814-qe-xxxx 815-sata-xxxx 816-sdhc-xxxx 817-spi-xxxx 818-thermal-xxxx 819-uart-xxxx 820-usb-xxxx 821-vfio-xxxx Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
		
			
				
	
	
		
			161 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			161 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From 3420c5bf9d08df074b67c7feda8a37d951d0b232 Mon Sep 17 00:00:00 2001
 | 
						|
From: Ioana Radulescu <ruxandra.radulescu@nxp.com>
 | 
						|
Date: Wed, 18 Sep 2019 13:31:07 +0300
 | 
						|
Subject: [PATCH] dpaa2-eth: Avoid unbounded while loops
 | 
						|
 | 
						|
Throughout the driver there are several places where we wait
 | 
						|
indefinitely for DPIO portal commands to be executed, while
 | 
						|
the portal returns a busy response code.
 | 
						|
 | 
						|
Even though in theory we are guaranteed the portals become
 | 
						|
available eventually, in practice the QBMan hardware module
 | 
						|
may become unresponsive in various corner cases.
 | 
						|
 | 
						|
Make sure we can never get stuck in an infinite while loop
 | 
						|
by adding a retry counter for all portal commands.
 | 
						|
 | 
						|
Signed-off-by: Ioana Radulescu <ruxandra.radulescu@nxp.com>
 | 
						|
---
 | 
						|
 drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 30 ++++++++++++++++++++----
 | 
						|
 drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h |  8 +++++++
 | 
						|
 2 files changed, 33 insertions(+), 5 deletions(-)
 | 
						|
 | 
						|
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
 | 
						|
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c
 | 
						|
@@ -221,6 +221,7 @@ static void xdp_release_buf(struct dpaa2
 | 
						|
 			    struct dpaa2_eth_channel *ch,
 | 
						|
 			    dma_addr_t addr)
 | 
						|
 {
 | 
						|
+	int retries = 0;
 | 
						|
 	int err;
 | 
						|
 
 | 
						|
 	ch->xdp.drop_bufs[ch->xdp.drop_cnt++] = addr;
 | 
						|
@@ -229,8 +230,11 @@ static void xdp_release_buf(struct dpaa2
 | 
						|
 
 | 
						|
 	while ((err = dpaa2_io_service_release(ch->dpio, priv->bpid,
 | 
						|
 					       ch->xdp.drop_bufs,
 | 
						|
-					       ch->xdp.drop_cnt)) == -EBUSY)
 | 
						|
+					       ch->xdp.drop_cnt)) == -EBUSY) {
 | 
						|
+		if (retries++ >= DPAA2_ETH_SWP_BUSY_RETRIES)
 | 
						|
+			break;
 | 
						|
 		cpu_relax();
 | 
						|
+	}
 | 
						|
 
 | 
						|
 	if (err) {
 | 
						|
 		free_bufs(priv, ch->xdp.drop_bufs, ch->xdp.drop_cnt);
 | 
						|
@@ -458,7 +462,7 @@ static int consume_frames(struct dpaa2_e
 | 
						|
 	struct dpaa2_eth_fq *fq = NULL;
 | 
						|
 	struct dpaa2_dq *dq;
 | 
						|
 	const struct dpaa2_fd *fd;
 | 
						|
-	int cleaned = 0;
 | 
						|
+	int cleaned = 0, retries = 0;
 | 
						|
 	int is_last;
 | 
						|
 
 | 
						|
 	do {
 | 
						|
@@ -469,6 +473,11 @@ static int consume_frames(struct dpaa2_e
 | 
						|
 			 * the store until we get some sort of valid response
 | 
						|
 			 * token (either a valid frame or an "empty dequeue")
 | 
						|
 			 */
 | 
						|
+			if (retries++ >= DPAA2_ETH_SWP_BUSY_RETRIES) {
 | 
						|
+				netdev_err_once(priv->net_dev,
 | 
						|
+						"Unable to read a valid dequeue response\n");
 | 
						|
+				return 0;
 | 
						|
+			}
 | 
						|
 			continue;
 | 
						|
 		}
 | 
						|
 
 | 
						|
@@ -477,6 +486,7 @@ static int consume_frames(struct dpaa2_e
 | 
						|
 
 | 
						|
 		fq->consume(priv, ch, fd, fq);
 | 
						|
 		cleaned++;
 | 
						|
+		retries = 0;
 | 
						|
 	} while (!is_last);
 | 
						|
 
 | 
						|
 	if (!cleaned)
 | 
						|
@@ -949,6 +959,7 @@ static int add_bufs(struct dpaa2_eth_pri
 | 
						|
 	u64 buf_array[DPAA2_ETH_BUFS_PER_CMD];
 | 
						|
 	struct page *page;
 | 
						|
 	dma_addr_t addr;
 | 
						|
+	int retries = 0;
 | 
						|
 	int i, err;
 | 
						|
 
 | 
						|
 	for (i = 0; i < DPAA2_ETH_BUFS_PER_CMD; i++) {
 | 
						|
@@ -980,8 +991,11 @@ static int add_bufs(struct dpaa2_eth_pri
 | 
						|
 release_bufs:
 | 
						|
 	/* In case the portal is busy, retry until successful */
 | 
						|
 	while ((err = dpaa2_io_service_release(ch->dpio, bpid,
 | 
						|
-					       buf_array, i)) == -EBUSY)
 | 
						|
+					       buf_array, i)) == -EBUSY) {
 | 
						|
+		if (retries++ >= DPAA2_ETH_SWP_BUSY_RETRIES)
 | 
						|
+			break;
 | 
						|
 		cpu_relax();
 | 
						|
+	}
 | 
						|
 
 | 
						|
 	/* If release command failed, clean up and bail out;
 | 
						|
 	 * not much else we can do about it
 | 
						|
@@ -1032,16 +1046,21 @@ static int seed_pool(struct dpaa2_eth_pr
 | 
						|
 static void drain_bufs(struct dpaa2_eth_priv *priv, int count)
 | 
						|
 {
 | 
						|
 	u64 buf_array[DPAA2_ETH_BUFS_PER_CMD];
 | 
						|
+	int retries = 0;
 | 
						|
 	int ret;
 | 
						|
 
 | 
						|
 	do {
 | 
						|
 		ret = dpaa2_io_service_acquire(NULL, priv->bpid,
 | 
						|
 					       buf_array, count);
 | 
						|
 		if (ret < 0) {
 | 
						|
+			if (ret == -EBUSY &&
 | 
						|
+			    retries++ >= DPAA2_ETH_SWP_BUSY_RETRIES)
 | 
						|
+				continue;
 | 
						|
 			netdev_err(priv->net_dev, "dpaa2_io_service_acquire() failed\n");
 | 
						|
 			return;
 | 
						|
 		}
 | 
						|
 		free_bufs(priv, buf_array, ret);
 | 
						|
+		retries = 0;
 | 
						|
 	} while (ret);
 | 
						|
 }
 | 
						|
 
 | 
						|
@@ -1094,7 +1113,7 @@ static int pull_channel(struct dpaa2_eth
 | 
						|
 						    ch->store);
 | 
						|
 		dequeues++;
 | 
						|
 		cpu_relax();
 | 
						|
-	} while (err == -EBUSY);
 | 
						|
+	} while (err == -EBUSY && dequeues < DPAA2_ETH_SWP_BUSY_RETRIES);
 | 
						|
 
 | 
						|
 	ch->stats.dequeue_portal_busy += dequeues;
 | 
						|
 	if (unlikely(err))
 | 
						|
@@ -1118,6 +1137,7 @@ static int dpaa2_eth_poll(struct napi_st
 | 
						|
 	struct netdev_queue *nq;
 | 
						|
 	int store_cleaned, work_done;
 | 
						|
 	struct list_head rx_list;
 | 
						|
+	int retries = 0;
 | 
						|
 	int err;
 | 
						|
 
 | 
						|
 	ch = container_of(napi, struct dpaa2_eth_channel, napi);
 | 
						|
@@ -1163,7 +1183,7 @@ static int dpaa2_eth_poll(struct napi_st
 | 
						|
 	do {
 | 
						|
 		err = dpaa2_io_service_rearm(ch->dpio, &ch->nctx);
 | 
						|
 		cpu_relax();
 | 
						|
-	} while (err == -EBUSY);
 | 
						|
+	} while (err == -EBUSY && retries++ < DPAA2_ETH_SWP_BUSY_RETRIES);
 | 
						|
 	WARN_ONCE(err, "CDAN notifications rearm failed on core %d",
 | 
						|
 		  ch->nctx.desired_cpu);
 | 
						|
 
 | 
						|
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h
 | 
						|
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.h
 | 
						|
@@ -245,6 +245,14 @@ static inline struct dpaa2_faead *dpaa2_
 | 
						|
  */
 | 
						|
 #define DPAA2_ETH_ENQUEUE_RETRIES	10
 | 
						|
 
 | 
						|
+/* Number of times to retry DPIO portal operations while waiting
 | 
						|
+ * for portal to finish executing current command and become
 | 
						|
+ * available. We want to avoid being stuck in a while loop in case
 | 
						|
+ * hardware becomes unresponsive, but not give up too easily if
 | 
						|
+ * the portal really is busy for valid reasons
 | 
						|
+ */
 | 
						|
+#define DPAA2_ETH_SWP_BUSY_RETRIES	1000
 | 
						|
+
 | 
						|
 /* Driver statistics, other than those in struct rtnl_link_stats64.
 | 
						|
  * These are usually collected per-CPU and aggregated by ethtool.
 | 
						|
  */
 |