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>
		
			
				
	
	
		
			253 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			253 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
From e89db675171a7a12f19b6ec0089a9cc62807cdf1 Mon Sep 17 00:00:00 2001
 | 
						|
From: Camelia Groza <camelia.groza@nxp.com>
 | 
						|
Date: Tue, 29 Oct 2019 16:34:08 +0200
 | 
						|
Subject: [PATCH] sdk_dpaa: ls1043a errata: update and optimize the
 | 
						|
 restrictions
 | 
						|
 | 
						|
An skb is in no danger of triggering the errata under the following
 | 
						|
conditions:
 | 
						|
- the paged data doesn't cross a 4K page boundary OR the linear data
 | 
						|
is aligned to 256 bytes when crossing a 4K page boundary
 | 
						|
- the linear and the paged data are 16 byte aligned
 | 
						|
- the paged data is a multiple of 16 bytes in size
 | 
						|
 | 
						|
Optimize the detection for each skb that might trigger the errata. Parse
 | 
						|
the skb twice, at most, and realign it only once.
 | 
						|
 | 
						|
Signed-off-by: Camelia Groza <camelia.groza@nxp.com>
 | 
						|
---
 | 
						|
 drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h |   2 +-
 | 
						|
 .../net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c  | 147 +++++++++++++++------
 | 
						|
 2 files changed, 111 insertions(+), 38 deletions(-)
 | 
						|
 | 
						|
--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h
 | 
						|
+++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth.h
 | 
						|
@@ -662,7 +662,7 @@ static inline void _dpa_bp_free_pf(void
 | 
						|
 #ifndef CONFIG_PPC
 | 
						|
 extern bool dpaa_errata_a010022; /* SoC affected by A010022 errata */
 | 
						|
 #define NONREC_MARK	0x01
 | 
						|
-#define HAS_DMA_ISSUE(start, size) \
 | 
						|
+#define CROSS_4K(start, size) \
 | 
						|
 	(((uintptr_t)(start) + (size)) > \
 | 
						|
 	 (((uintptr_t)(start) + 0x1000) & ~0xFFF))
 | 
						|
 /* The headroom needs to accommodate our private data (64 bytes) but
 | 
						|
--- a/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c
 | 
						|
+++ b/drivers/net/ethernet/freescale/sdk_dpaa/dpaa_eth_sg.c
 | 
						|
@@ -771,32 +771,73 @@ int __hot skb_to_contig_fd(struct dpa_pr
 | 
						|
 EXPORT_SYMBOL(skb_to_contig_fd);
 | 
						|
 
 | 
						|
 #ifndef CONFIG_PPC
 | 
						|
-/* Verify the conditions that trigger the A010022 errata: data unaligned to
 | 
						|
- * 16 bytes, 4K memory address crossings and S/G fragments.
 | 
						|
+/* Verify the conditions that trigger the A010022 errata:
 | 
						|
+ * - 4K memory address boundary crossings when the data/SG fragments aren't
 | 
						|
+ *   aligned to 256 bytes
 | 
						|
+ * - data and SG fragments that aren't aligned to 16 bytes
 | 
						|
+ * - SG fragments that aren't mod 16 bytes in size (except for the last
 | 
						|
+ *   fragment)
 | 
						|
  */
 | 
						|
 static bool a010022_check_skb(struct sk_buff *skb, struct dpa_priv_s *priv)
 | 
						|
 {
 | 
						|
-	/* Check if the headroom is aligned */
 | 
						|
-	if (((uintptr_t)skb->data - priv->tx_headroom) %
 | 
						|
-	    priv->buf_layout[TX].data_align != 0)
 | 
						|
-		return true;
 | 
						|
+	skb_frag_t *frag;
 | 
						|
+	int i, nr_frags;
 | 
						|
 
 | 
						|
-	/* Check for paged data in the skb. We do not support S/G fragments */
 | 
						|
-	if (skb_is_nonlinear(skb))
 | 
						|
+	nr_frags = skb_shinfo(skb)->nr_frags;
 | 
						|
+
 | 
						|
+	/* Check if the linear data is 16 byte aligned */
 | 
						|
+	if ((uintptr_t)skb->data % 16)
 | 
						|
 		return true;
 | 
						|
 
 | 
						|
-	/* Check if the headroom crosses a boundary */
 | 
						|
-	if (HAS_DMA_ISSUE(skb->head, skb_headroom(skb)))
 | 
						|
+	/* Check if the needed headroom crosses a 4K address boundary without
 | 
						|
+	 * being 256 byte aligned
 | 
						|
+	 */
 | 
						|
+	if (CROSS_4K(skb->data - priv->tx_headroom, priv->tx_headroom) &&
 | 
						|
+	    (((uintptr_t)skb->data - priv->tx_headroom) % 256))
 | 
						|
 		return true;
 | 
						|
 
 | 
						|
-	/* Check if the non-paged data crosses a boundary */
 | 
						|
-	if (HAS_DMA_ISSUE(skb->data, skb_headlen(skb)))
 | 
						|
+	/* Check if the linear data crosses a 4K address boundary without
 | 
						|
+	 * being 256 byte aligned
 | 
						|
+	 */
 | 
						|
+	if (CROSS_4K(skb->data, skb_headlen(skb)) &&
 | 
						|
+	    ((uintptr_t)skb->data % 256))
 | 
						|
 		return true;
 | 
						|
 
 | 
						|
-	/* Check if the entire linear skb crosses a boundary */
 | 
						|
-	if (HAS_DMA_ISSUE(skb->head, skb_end_offset(skb)))
 | 
						|
+	/* When using Scatter/Gather, the linear data becomes the first
 | 
						|
+	 * fragment in the list and must follow the same restrictions as the
 | 
						|
+	 * other fragments.
 | 
						|
+	 *
 | 
						|
+	 * Check if the linear data is mod 16 bytes in size.
 | 
						|
+	 */
 | 
						|
+	if (nr_frags && (skb_headlen(skb) % 16))
 | 
						|
 		return true;
 | 
						|
 
 | 
						|
+	/* Check the SG fragments. They must follow the same rules as the
 | 
						|
+	 * linear data with and additional restriction: they must be multiple
 | 
						|
+	 * of 16 bytes in size to account for the hardware carryover effect.
 | 
						|
+	 */
 | 
						|
+	for (i = 0; i < nr_frags; i++) {
 | 
						|
+		frag = &skb_shinfo(skb)->frags[i];
 | 
						|
+
 | 
						|
+		/* Check if the fragment is a multiple of 16 bytes in size.
 | 
						|
+		 * The last fragment is exempt from this restriction.
 | 
						|
+		 */
 | 
						|
+		if ((i != (nr_frags - 1)) && (skb_frag_size(frag) % 16))
 | 
						|
+			return true;
 | 
						|
+
 | 
						|
+		/* Check if the fragment is 16 byte aligned */
 | 
						|
+		if (skb_frag_off(frag) % 16)
 | 
						|
+			return true;
 | 
						|
+
 | 
						|
+		/* Check if the fragment crosses a 4K address boundary. Since
 | 
						|
+		 * the alignment of previous fragments can influence the
 | 
						|
+		 * current fragment, checking for the 256 byte alignment
 | 
						|
+		 * isn't relevant.
 | 
						|
+		 */
 | 
						|
+		if (CROSS_4K(skb_frag_off(frag), skb_frag_size(frag)))
 | 
						|
+			return true;
 | 
						|
+	}
 | 
						|
+
 | 
						|
 	return false;
 | 
						|
 }
 | 
						|
 
 | 
						|
@@ -1062,10 +1103,24 @@ int __hot dpa_tx_extended(struct sk_buff
 | 
						|
 	struct dpa_percpu_priv_s *percpu_priv;
 | 
						|
 	struct rtnl_link_stats64 *percpu_stats;
 | 
						|
 	int err = 0;
 | 
						|
-	bool nonlinear;
 | 
						|
+	bool nonlinear, skb_changed, skb_need_wa;
 | 
						|
 	int *countptr, offset = 0;
 | 
						|
 	struct sk_buff *nskb;
 | 
						|
 
 | 
						|
+	/* Flags to help optimize the A010022 errata restriction checks.
 | 
						|
+	 *
 | 
						|
+	 * First flag marks if the skb changed between the first A010022 check
 | 
						|
+	 * and the moment it's converted to an FD.
 | 
						|
+	 *
 | 
						|
+	 * The second flag marks if the skb needs to be realigned in order to
 | 
						|
+	 * avoid the errata.
 | 
						|
+	 *
 | 
						|
+	 * The flags should have minimal impact on platforms not impacted by
 | 
						|
+	 * the errata.
 | 
						|
+	 */
 | 
						|
+	skb_changed = false;
 | 
						|
+	skb_need_wa = false;
 | 
						|
+
 | 
						|
 	priv = netdev_priv(net_dev);
 | 
						|
 	/* Non-migratable context, safe to use raw_cpu_ptr */
 | 
						|
 	percpu_priv = raw_cpu_ptr(priv->percpu_priv);
 | 
						|
@@ -1075,13 +1130,8 @@ int __hot dpa_tx_extended(struct sk_buff
 | 
						|
 	clear_fd(&fd);
 | 
						|
 
 | 
						|
 #ifndef CONFIG_PPC
 | 
						|
-	if (unlikely(dpaa_errata_a010022) && a010022_check_skb(skb, priv)) {
 | 
						|
-		nskb = a010022_realign_skb(skb, priv);
 | 
						|
-		if (!nskb)
 | 
						|
-			goto skb_to_fd_failed;
 | 
						|
-		dev_kfree_skb(skb);
 | 
						|
-		skb = nskb;
 | 
						|
-	}
 | 
						|
+	if (unlikely(dpaa_errata_a010022) && a010022_check_skb(skb, priv))
 | 
						|
+		skb_need_wa = true;
 | 
						|
 #endif
 | 
						|
 
 | 
						|
 	nonlinear = skb_is_nonlinear(skb);
 | 
						|
@@ -1102,8 +1152,8 @@ int __hot dpa_tx_extended(struct sk_buff
 | 
						|
 	 * Btw, we're using the first sgt entry to store the linear part of
 | 
						|
 	 * the skb, so we're one extra frag short.
 | 
						|
 	 */
 | 
						|
-	if (nonlinear &&
 | 
						|
-		likely(skb_shinfo(skb)->nr_frags < DPA_SGT_MAX_ENTRIES)) {
 | 
						|
+	if (nonlinear && !skb_need_wa &&
 | 
						|
+	    likely(skb_shinfo(skb)->nr_frags < DPA_SGT_MAX_ENTRIES)) {
 | 
						|
 		/* Just create a S/G fd based on the skb */
 | 
						|
 		err = skb_to_sg_fd(priv, skb, &fd);
 | 
						|
 		percpu_priv->tx_frag_skbuffs++;
 | 
						|
@@ -1128,39 +1178,62 @@ int __hot dpa_tx_extended(struct sk_buff
 | 
						|
 
 | 
						|
 			dev_kfree_skb(skb);
 | 
						|
 			skb = skb_new;
 | 
						|
+			skb_changed = true;
 | 
						|
 		}
 | 
						|
 
 | 
						|
 		/* We're going to store the skb backpointer at the beginning
 | 
						|
 		 * of the data buffer, so we need a privately owned skb
 | 
						|
+		 *
 | 
						|
+		 * Under the A010022 errata, we are going to have a privately
 | 
						|
+		 * owned skb after realigning the current one, so no point in
 | 
						|
+		 * copying it here in that case.
 | 
						|
 		 */
 | 
						|
 
 | 
						|
 		/* Code borrowed from skb_unshare(). */
 | 
						|
-		if (skb_cloned(skb)) {
 | 
						|
+		if (skb_cloned(skb) && !skb_need_wa) {
 | 
						|
 			nskb = skb_copy(skb, GFP_ATOMIC);
 | 
						|
 			kfree_skb(skb);
 | 
						|
 			skb = nskb;
 | 
						|
-#ifndef CONFIG_PPC
 | 
						|
-			if (unlikely(dpaa_errata_a010022) &&
 | 
						|
-			    a010022_check_skb(skb, priv)) {
 | 
						|
-				nskb = a010022_realign_skb(skb, priv);
 | 
						|
-				if (!nskb)
 | 
						|
-					goto skb_to_fd_failed;
 | 
						|
-				dev_kfree_skb(skb);
 | 
						|
-				skb = nskb;
 | 
						|
-			}
 | 
						|
-#endif
 | 
						|
+			skb_changed = true;
 | 
						|
+
 | 
						|
 			/* skb_copy() has now linearized the skbuff. */
 | 
						|
-		} else if (unlikely(nonlinear)) {
 | 
						|
+		} else if (unlikely(nonlinear) && !skb_need_wa) {
 | 
						|
 			/* We are here because the egress skb contains
 | 
						|
 			 * more fragments than we support. In this case,
 | 
						|
 			 * we have no choice but to linearize it ourselves.
 | 
						|
 			 */
 | 
						|
-			err = __skb_linearize(skb);
 | 
						|
+#ifndef CONFIG_PPC
 | 
						|
+			/* No point in linearizing the skb now if we are going
 | 
						|
+			 * to realign and linearize it again further down due
 | 
						|
+			 * to the A010022 errata
 | 
						|
+			 */
 | 
						|
+			if (unlikely(dpaa_errata_a010022))
 | 
						|
+				skb_need_wa = true;
 | 
						|
+			else
 | 
						|
+#endif
 | 
						|
+				err = __skb_linearize(skb);
 | 
						|
 		}
 | 
						|
 		if (unlikely(!skb || err < 0))
 | 
						|
 			/* Common out-of-memory error path */
 | 
						|
 			goto enomem;
 | 
						|
 
 | 
						|
+#ifndef CONFIG_PPC
 | 
						|
+		/* Verify the skb a second time if it has been updated since
 | 
						|
+		 * the previous check
 | 
						|
+		 */
 | 
						|
+		if (unlikely(dpaa_errata_a010022) && skb_changed &&
 | 
						|
+		    a010022_check_skb(skb, priv))
 | 
						|
+			skb_need_wa = true;
 | 
						|
+
 | 
						|
+		if (unlikely(dpaa_errata_a010022) && skb_need_wa) {
 | 
						|
+			nskb = a010022_realign_skb(skb, priv);
 | 
						|
+			if (!nskb)
 | 
						|
+				goto skb_to_fd_failed;
 | 
						|
+			dev_kfree_skb(skb);
 | 
						|
+			skb = nskb;
 | 
						|
+		}
 | 
						|
+#endif
 | 
						|
+
 | 
						|
 		err = skb_to_contig_fd(priv, skb, &fd, countptr, &offset);
 | 
						|
 	}
 | 
						|
 	if (unlikely(err < 0))
 |